示例:app
class Person: country = "China" def __init__(self, name, age): self.name = name self.age = age def speak(self, word): print(word)
其中 country 是类属性,即 Person类 的静态属性,speak() 为 Person类的函数属性,即类的动态属性~ide
对上述示例的类进行实例化:函数
>>> p = Person('Kitty', 18) # 实例化 Person类,获得对象 p >>> p.name # 调用对象 p 的name属性 'Kitty' >>> p.speak('hello') # 调用对象 p 的绑定方法 hello
类中的 __init__ 方法用于初始化对象,而在类的是实例化过程当中,对应类中第一个被调用的并非 __init__ 方法,第一个被调用的是 __new__方法。在对象的初始化以前首先要建立对象,__new__方法正是用来建立这个对象~
类的实例化过程也能够经过以下语句来实现:.net
>>> p = object.__new__(Person) # __new__方法继承自 object类 >>> Person.__init__(p, 'Kitty', 18) >>> p.name 'Kitty'
在Person类中重写 __new__方法:code
class Person: country = "China" def __new__(cls, name, age): print('__new__ called') return super(Person, cls).__new__(cls) def __init__(self, name, age): self.name = name self.age = age def speak(self, word): print(word) p = Person('Kitty', 18) # 实例化对象 print('name : %s' % p.name) # 输出结果: __new__ called name : Kitty
很明显 __new__方法 是先于 __init__ 方法被调用的~
类的实例化过程大体步骤以下:
一、p = Person('Kitty', 18) ,会调用 Person类的__new__方法,并传递 name 和 age 参数
二、__new__方法 会建立一个 Person类的对象并返回
三、最后利用这个对象调用类的 __init__ 方法 完成初始化,__init__ 方法的第一个参数是self,对象在调用 __init__ 方法时会将本身当作参数传递给 这个self。
注意:__init__方法没有返回值~,__init__ 方法仅完成对象的初始化工做~
对象
self是什么?
在类的内部,self 就是一个对象。使用对象调用方法时(对象的绑定方法),当前对象会被自动传递给 self,即 self 表示调用该方法的对象~blog
操做类的变量属性:继承
>>> Person.country # 调用类属性 'China' >>> Person.country = 'USA' # 修改类属性 >>> Person.country 'USA' >>> del Person.country # 删除类属性 >>> Person.country # 删除后没法再调用 Traceback (most recent call last): File "<stdin>", line 1, in <module> AttributeError: type object 'Person' has no attribute 'country'
调用类的函数属性:
这里仅介绍绑定方法的调用(即第一个参数是self的方法),类中的其余方法暂先不作介绍~
speak() 是类的函数属性,对象调用不须要传递 self参数(对象调用 会自动完成self参数传值,下面会介绍),如果类来调用,则须要手动传递这个 self参数,即须要传递一个Person类的对象~ip
class Person: country = "China" def __init__(self, name, age): self.name = name self.age = age def speak(self, word): print(word) p = Person('Kitty', 18) p.speak('hello') # 对象调用,会自动将 对象p 做为第一个参数传递给 self Person.speak(p, '你好') # 类调用须要手动传递 self 的值 # 输出结果: hello 你好
类名.__dict__ 用来查看一个类(或对象)的名称空间,能够这样理解。其实__dict__是类的一个内置属性,存储全部实例共享的变量和函数(类属性,方法等),类的__dict__并不包含其父类的属性。对象中的 __dict__ 属性下面会介绍~
这里注意和 dir() 方法的区别,dir(类名或对象名) 会返回一个类(或对象)的全部属性,包括从父类中继承的属性。内存
Person类的__dict__属性 {'__module__': '__main__', # 所处模块 '__init__': <function Person.__init__ at 0x11023b378>, # __init__方法 'speak': <function Person.speak at 0x11023b400>, # speak 方法 '__dict__': <attribute '__dict__' of 'Person' objects>, # 应该就是指 类的__dict__属性,具体参阅:https://blog.csdn.net/lis_12/article/details/53519060 '__weakref__': <attribute '__weakref__' of 'Person' objects>, '__doc__': None} # # class说明文档
调用类的属性,首先会去类的名称空间中(Person.__dict__)寻找对应名称的key,至关于Person.__dict__['country'],也能够直接这样调用:
>>> Person.__dict__['country'] 'China' >>> Person.__dict__['country'] = 'USA' Traceback (most recent call last): File "<stdin>", line 1, in <module> TypeError: 'mappingproxy' object does not support item assignment
注意:
__dict__ 对于类中的属性只能查看,不能修改~
除了 __dict__,Python中的类还有不少别的内置属性:
__doc__ :类的说明
__name__: 类名
__module__: 类定义所在的模块
__bases__ : 包含了类的全部父类 的元组
示例以下:
class Person: '''human being''' country = "China" def __init__(self, name, age): self.name = name self.age = age def speak(self, word): print(word) print(Person.__doc__) print(Person.__name__) print(Person.__module__) print(Person.__bases__) #结果输出: human being Person __main__ (<class 'object'>,)
class Person: country = "China" def __init__(self, name, age): self.name = name self.age = age def speak(self, word): print(word)
实例化一个Person类的对象 的过程当中,init方法会将参数赋值给 name 与 age 属性,能够经过 实例的__dict__ 查看,注意:实例的__dict__ 仅存储与该实例相关的实例属性,没有函数属性,也没有共有属性~
>>> p = Person('Kitty', 18) >>> print(p.__dict__) {'name': 'Kitty', 'age': 18}
注意 实例.__dict__ 与 类.__dict__ 的区别~
经过 类.__dict__ 能够查看类中的属性,可是不能修改,可是经过 实例.__dict__ 除了查看,还能够进行修改~
>>> p.__dict__['name'] 'Kitty' >>> p.__dict__['age'] 18 >>> p.__dict__['name'] = 'abc' >>> p.__dict__['age'] = 20 >>> p.name 'abc' >>> p.age 20
经过对象能够直接调用该对象的变量属性,例如 p对象 的 name属性 和 age属性~
>>> p = Person('Kitty', 18) >>> p.name 'Kitty' >>> p.age 18
也能够经过 p对象 调用对应类(这里是Person类)的变量属性,如果类的变量属性发生变化,则全部对象获取到的类变量属性都会改变~
>>> p.country 'China' >>> Person.country = 'UK' # 修改 类的变量属性 >>> p2 = Person('baby', 22) >>> p.country 'UK' >>> p2.country 'UK'
Tip:
注意1
在修改类的变量属性时,若变量是不可变类型,则仅能经过 类名.变量属性 来修改,以下示例:
>>> Person.country = 'USA' # 修改类属性 >>> p.country 'USA' >>> p.country = 'UK' >>> p.country 'UK' >>> Person.country 'USA' >>> p2.country 'USA'
p.country 并无修改类属性,而是给本身添加了一个新的属性,这个新添加的属性存放在对象本身的名称空间中,类的变量属性 country 并无发生改变~
>>> p.__dict__ {'country': 'UK', 'age': 20, 'name': 'abc'}
在类中 self 表示当前调用的对象,当 self 引用的变量和类变量同名的时候,须要注意区分:这两个变量之间没有关联,self 引用的变量属于对象,放在对象的名称空间中,类变量则放在类名称空间中
class Person: country = "China" def __init__(self, name, age): self.name = name self.age = age self.country = 'AUS' # 添加对象属性 def speak(self): print(self.country) ############ >>> p = Person('Kitty', 18) >>> p.country 'AUS' >>> p.speak() AUS >>> Person.country 'China'
注意2
当类变量为可变类型时,须要区分对象的 2种 操做:
class Person: country = "China" lst = [] def __init__(self, name, age): self.name = name self.age = age self.lst.append(name) def speak(self): print(self.name) ############ >>> p = Person('Kitty', 18) >>> p.__dict__ {'age': 18, 'name': 'Kitty'} >>> Person.lst ['Kitty']
上述示例中,self 针对 lst 变量并非一个赋值操做,而是调用了 lst的append方法,因此这个过程会先在对象的名称空间中寻找 lst 属性,对象的名称空间中没有,而后再去类的名称空间中寻找,Person类中存在该属性,因而调用其 append 方法。
这个过程经过对象修改了类的可变类型的变量~
若 self 针对 lst 变量是一个赋值操做,这样就为当前对象新增了一个 lst 属性
class Person: country = "China" lst = [] def __init__(self, name, age): self.name = name self.age = age self.lst = name def speak(self): print(self.name) ############ >>> p = Person('Kitty', 18) >>> p.__dict__ {'age': 18, 'name': 'Kitty', 'lst': 'Kitty'} >>> Person.__dict__ {'__module__': '__main__', 'country': 'China', 'lst': [], '__doc__': None, '__init__': <function __init__ at 0x105f5fc08>, 'speak': <function speak at 0x105f5c0c8>}
class Person: country = "China" def __init__(self, name, age): self.name = name self.age = age def speak(self): print(self.name + ', ' + str(self.age)) ############ >>> p1 = Person('Kitty', 18) >>> p2 = Person('baby', 22) >>> p1.__dict__ {'age': 18, 'name': 'Kitty'} >>> p2.__dict__ {'age': 22, 'name': 'baby'}
能够看到对象的名称空间中没有函数属性,函数属性在类的名称空间当中
>>> Person.speak <unbound method Person.speak> >>> p1.speak <bound method Person.speak of <__main__.Person instance at 0x105f727a0>> >>> p2.speak <bound method Person.speak of <__main__.Person instance at 0x105f728c0>>
p1 和 p2 的 speak 方法为绑定方法(bound method),且 p1 和 p2 的 speak 方法内存地址不一致,这两个对象的 speak 方法都执行 类中对应的方法。
绑定方法,有两种:绑定到类的方法和绑定到对象的方法,上述示例中的方法为后者,绑定到对象的方法为对象专门定制,使用对象调用的时候,会自动将 当前对象传递给方法的第一个参数(self,通常都叫self,也能够写成别的名称),若使用类调用,则第一个参数须要手动传值~
>>> p1.speak() Kitty, 18 >>> p2.speak() baby, 22 >>> Person.speak(p1) # 经过类调用 Kitty, 18
这里仅对绑定到对象的方法作简单介绍,类中还有绑定到类的方法,还有非绑定方法等...,以后会介绍
.................^_^