前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >您好,这里有一份 “实例”请您接收一下。

您好,这里有一份 “实例”请您接收一下。

作者头像
编程文青李狗蛋
发布2019-11-07 15:38:35
2300
发布2019-11-07 15:38:35
举报
写在之前

昨天写了类属性,作为不分家的小伙伴,今天当然是来说说 “实例”。我在之前的文章中说过,类是对象的定义,实例才是真实的东西。比如 “人” 是一个类,但是 “人” 终究不是具体的某个会喘气的,只有 “rocky” 才是具体的东西,但他是具有 “人” 这个类所定义的属性和方法。“rocky” 就是 “人” 这个类的实例。

创建实例

创建实例并不是很难的事情,只需要调用类就可以实现:

代码语言:javascript
复制
>>> class man():
...     sex = '男'
...
>>> rocky = man()
>>> rocky
<__main__.man instance at 0x00000000004F3688>

如果不是用很严格的说法的话,上面的这个例子就是创建了一个实例 rocky。这里有一点需要我们注意的是,调用类的方法和调用类的函数类似,如果仅仅是写 man() 的话,则是创建了一个实例:

代码语言:javascript
复制
>>> man()
<__main__.man instance at 0x0000000002577D88>

而 rocky = man() 本质上是将变量 rocky 与实例对象 man() 建立引用关系,这种关系就如同我们在刚开始的时候学的赋值语句 x = 1 是同样的效果。

那么对于一个实例来说这个建立的过程是怎么进行的呢?我们继续来看:

代码语言:javascript
复制
class Person:
   """
   具有通常类的结构的 Person 类
   """
   def __init__(self,name):
       self.name = name

   def get_name(self):
       return self.name

   def get_sex(self,sex):
       per_sex = {}
       per_sex[self.name] = sex
       return per_sex

实例我们用 boy = Person('rocky') ,当然了,在这里你可以创建很多个实例,还记得那句话么:类是实例的工厂。

当我们创建完实例,接下来就是调用类,当类被调用以后,先是创建一个实例对象,然后检查是否有 __init__(),如果有的话就调用这个方法,并且将实例对象作为第一个参数 self 传进去,如果没有的话,就只是返回实例对象。

我之前也说过,__init__() 作为一个方法是比较特殊的,在它里面,一般是规定一些属性或者做一些初始化,让类具有一些基本的属性,但是它没有 return 语句,这是 __init__() 区别于一般方法的地方:

代码语言:javascript
复制
>>> class fun:
...     def __init__(self):
...             print('this is init()')
...             return 1
...
>>> f = fun()
this is init()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __init__() should return None

上面的运行结果出现了异常,并且明确说明了 “__init__() should return None”,所以不能有 return,如果非要带上的话,只能是 return None,索性就不要写了。

由此可知对于 __init__() ,除了第一个参数必须是 self,还要求不能有 return 语句,其他方面和普通函数就没有什么区别了。比如参数和里面的属性,你就可以像下面这样来做:

代码语言:javascript
复制
>>> class Person:
...     def __init__(self,name,sex = '男',age = 10):
...             self.name = name
...             self.sex = sex
...             self.age = age
...

实例我们创建好了以后,我们接下来就要研究实例的内容,首先来看的是实例属性。

实例属性

和类属性相似,实例所具有的属性叫做 “实例属性”:

代码语言:javascript
复制
>>> class A:
...     x = 1
...
>>> f = A()

类已经有了一个属性 A.x = 1,那么由类所创建的实例也应当具有这个属性:

代码语言:javascript
复制
>>> f.x
1

除了 f.x 这个属性以外,实例也具有其它的属性和方法,我们依然用 dir 方法来看:

代码语言:javascript
复制
>>> dir(f)
['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'x']

实例属性和类属性最主要的不同是在于,实例属性可以随意的更改:

代码语言:javascript
复制
>>> f.x += 10
>>> f.x
11

上面就是把实例属性修改了,但是类属性并没有因为实例属性的修改而发生变化,正如我们在前几天的文章中所说的那样,类属性是与类捆绑的,不受实例的影响。

代码语言:javascript
复制
>>> A.x
1

上述的结果正好印证了这一点 -- 类属性不因实例属性改变而改变。既然如此,那么 f.x += 10 又改变了什么呢?

其实就是实例 f 又重新建立了一个新的属性,但是这个新的属性和原先旧的属性是一个名字,都是 f.x,所以相当于原先旧的属性被 “掩盖”了,只能访问到新的属性,所以值是 11。

代码语言:javascript
复制
>>> f.x
11
>>> del f.x
>>> f.x
1

由上面的例子可以看出,既然新的 f.x “掩盖”了旧的 f.x,只要把新的 f.x 删除,旧的 f.x 就可以显现出来。

实例的改变不会影响到类,但是类属性可以影响到实例属性,因为实例就是通过调用类来建立的:

代码语言:javascript
复制
>>> A.x += 10
>>> A.x
11
>>> f.x
11

如果是同一个属性 x,那么实例属性跟着类属性的改变而改变,当然,这个是针对于像字符串这种不可变对象而言的,对于类中如果引用的是可变对象的数据,则情形会有所不同,因为可变对象的数据是可以原地进行修改的

代码语言:javascript
复制
>>> class B:
...     y = [1,2,3,4]
...
>>> B.y #类属性
[1, 2, 3, 4]
>>> f = B()
>>> f.y #实例属性
[1, 2, 3, 4]
>>> B.y.append('5')
>>> B.y
[1, 2, 3, 4, '5']
>>> f.y
[1, 2, 3, 4, '5']
>>> f.y.append('66')
>>> B.y
[1, 2, 3, 4, '5', '66']
>>> f.y
[1, 2, 3, 4, '5', '66']

通过上面的代码我们可以看出,当类中的变量引用的是可变对象的时候,类属性和实例属性都能够直接修改这个对象,从而增加另一方的值。

还有一点我们已经知道了增加一个类属性,相应的实例属性也会增加,但是反过来就不成立了:

代码语言:javascript
复制
>>> B.x = 'aa'
>>> f.x
'aa'
>>> f.z = 'abcd'
>>> f.z
'abcd'
>>> B.z
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: class B has no attribute 'z'

可以看出类并没有接纳实例实例增加的属性。

写在最后

这一篇文章写得有点多,我本来想分为两次来写的,但是因为都是实例,所以放在了一起,两相印证一下,可能印象会更深。

在写这篇文章的时候,查了一些资料,看到几个之前没有注意到的点,我也在文章中给大家提醒了,知识就是这样,有很多你会忽略的东西,永远不要觉得基础不重要,也永远不要小看 “简单” 这个词。

希望你看了就要好好看,不要浪费你的时间,也请珍惜我的劳动成果。

The end。

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-08-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Python空间 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档