四、面向对象进阶
1、类方法
普通的方法通过对象调用,至少有一个self参数(调用的时候系统自动传递,不需要手工传递),而类方法由类直接调用,至少有一个cls参数,执行时,自动将调用该方法的类赋值个cls
1
2
3
4
5
6
7
8
|
class Foo( object ): def __init__( self ): pass @classmethod # 类方法装饰器,通过他把一个方法装饰成类方法 def class_func( cls ): # cls参数就是这个类本身,注意与self不同,self表示类的对象本身 print ( 'class_func' , cls ) if __name__ = = '__main__' : Foo.class_func() |
2、静态方法
由类调用,没有默认参数
1
2
3
4
5
6
7
8
|
class Foo( object ): def __init__( self ): pass @staticmethod # 静态方法装饰器,通过他把一个方法装饰成静态方法 def static_func(): # 与类方法不同的是没有默认参数cls print ( 'static_func' ) if __name__ = = '__main__' : Foo.class_func() |
3、属性
由对象调用,除了self不能有其他参数,调用的时候不用(),看上去就像变量一样,但其实本质还是一个方法,可以通过return把一串执行过程的返回结果返回,从外面看就像是一个只读的变量
1
2
3
4
5
6
7
8
9
|
class Foo( object ): def __init__( self , count): self .__count = count @property # 属性装饰器,通过他把一个方法装饰成属性 def count( self ): return self .__count if __name__ = = '__main__' : obj = Foo( 1 ) print (obj.count) # 从外面调用的时候不用()看上去就像一个变量 |
属性的主要功能就是将内部复杂的逻辑计算得出的记过返回,所以建议最好有返回值,并且内部不要有print()否则虽然语法上不报错,并且的确没有啥问题,但失去了存在的意义。
到目前为止属性和变量相比还只是只读的,我们可以通过@属性名.setter装饰器定义一个修改属性的方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
class Foo( object ): def __init__( self , count): self .__count = count @property # 属性装饰器,通过他把一个方法装饰成属性 def count( self ): return self .__count @count .setter def count( self , value): # 这里除了self只能有一个参数 self .__count = value if __name__ = = '__main__' : obj = Foo( 1 ) print (obj.count) obj.count = 2 # 解释器会自动把赋值号后面的值作为参数传递给方法 print (obj.count) |
另外变量还可通过del关键字进行销毁,属性同样可以
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
class Foo( object ): def __init__( self , count): self .__count = count @property # 属性装饰器,通过他把一个方法装饰成属性 def count( self ): return self .__count @count .setter def count( self , value): # 这里除了self只能有一个参数 self .__count = value @count .deleter def count( self ): # 这里除了self不能有其他参数 del self .__count if __name__ = = '__main__' : obj = Foo( 1 ) del obj.count # 解释遇到del关键字自动调用对应的deleter方法 |
到此,一个属性和变量的最大区别就只剩下变量就是一个变量而属性可以内部执行一大堆逻辑
4、成员修饰符__
通过两个下划线“__”,修饰的都是私有,仅仅只是内部进行调用,并且不能继承(要特别注意,有中很贴切的说法形容私有,父亲的钱、房子儿子是共有的可以继承,父亲的女人是私有的,不可以继承),包裹类变量,实例变量,方法等都可以使用__修饰变成私有的
1
2
3
4
5
6
|
class Foo( object ): __name = 'name' # 私有类变量 def __init__( self ): self .__age # 私有成员变量 def __funce( self ): # 私有方法 pass |
5、特殊成员
有一些成员不需要定义,解释器会自动加载,可以理解为这些都是继承自object
__init__:
构造方法,这里就不多说了,通过类创建对象时,自动触发执行
__doc__:
表示类的描述信息
1
2
3
4
5
6
7
8
9
|
class Foo( object ): ''' 类的描述信息 ''' def __init__( self ): pass if __name__ = = '__main__' : print (Foo.__doc__) |
输出结果
1
|
类的描述信息 |
__module__和__class__
__module__ 表示这个或对象属于哪个模块
__class__ 表示对象属于哪个类
1
2
3
4
5
6
7
8
9
10
11
|
class Foo( object ): ''' 类的描述信息 ''' def __init__( self ): pass if __name__ = = '__main__' : print (Foo.__module__) obj = Foo() print (obj.__class__) |
输出结果
1
2
|
__main__ < class '__main__.Foo' > |
__del__
析构方法,当对象在内存中销毁的时候自动触发执行
1
2
3
4
5
6
|
class Foo( object ): def __del__( self ): print ( 'del object' ) if __name__ = = '__main__' : obj = Foo() |
执行结果
1
|
del object |
说明:Python解释器有自己的内存回收机制,这里当程序执行完了的是否触发析构方法,也可以使用del关键字手动销毁对象触发
__call__
在Python中,对象后面加括号,就会触发这个方法,如果没有这个方法就不可以。
1
2
3
4
5
6
7
|
class Foo( object ): def __call__( self ): print ( '__call__ is exec' ) if __name__ = = '__main__' : obj = Foo() obj() |
执行结果
1
|
__call__ is exec |
__dict__
类或者对象中的所有成员
1
2
3
4
5
6
7
8
9
10
11
12
13
|
class Province(object): country = 'China' def __init__( self , name): self .name = name def func( self ): pass if __name__ = = '__main__' : print ( 'Class dict:' , Province.__dict__) obj = Province( 'zhangsan' ) print ( 'Object dict:' , obj.__dict__) |
输出结果
1
2
|
Class dict : { '__weakref__' : <attribute '__weakref__' of 'Province' objects>, '__module__' : '__main__' , 'func' : <function Province.func at 0x0000023BD2288950 >, 'country' : 'China' , '__init__' : <function Province.__init__ at 0x0000023BD22888C8 >, '__dict__' : <attribute '__dict__' of 'Province' objects>, '__doc__' : None } Object dict : { 'name' : 'zhangsan' } |
说明:可以看出只有name是属于对象的,其他的都是属于类的,也就是说所有的方法都是属于类而不属于对象,当执行对象名.方法名()调用方法的时候,Python解释器会自动将对象本身作为方法的第一个参数传递给方法,也就是方法里self参数。
__str__
如果类中定义了一个__str__方法,当我们打印这个类的实例的时候回调用这个方法的返回值,所以这个方法必须有return,否则就会报错(TypeError: __str__ returned non-string (type NoneType))
1
2
3
4
5
6
7
8
|
class Foo( object ): def __str__( self ): return 'Foo object' #class Foo() if __name__ = = '__main__' : obj = Foo() print (obj) |
输出结果
1
|
Foo object |