目录:
1.装饰一个类
2.类方法和静态方法
1.装饰一个类
为一个类增加一些属性:
>>> def add_name(name,cls):
... cls.NAME = name
>>> def add_name(name):
... def wrapper(cls):
... cls.NAME = name
... return cls
... return wrapper
>>> @add_name('Tom')
... class Person:
... AGE = 3
>>> print(Person.NAME)
Tom
本质上是为类对象动态的添加一个属性,而Person这个标识符指向这个类对象
2.类方法和静态方法
前面的例子中定义的__init__等方法,这些方法本身都是类的属性,第一个参数必须是self,而self必须指向一个对象,也就是类实例化之后,由实例来调用这些方法。
2.1普通函数
>>> class Person:
... def normal_method():
... print('normal')
>>> Person.normal_method()
normal
>>> Person().normal_method()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: normal_method() takes 0 positional arguments but 1 was given
>>> print(Person.__dict__)
{
'__module__': '__main__',
'normal_method': <function Person.normal_method at 0x7fc6612e3820>,
'__dict__': <attribute '__dict__' of 'Person' objects>,
'__weakref__': <attribute '__weakref__' of 'Person' objects>,
'__doc__': None
}
Person.normal_method()可以放在类中定义,因为这个方法只是被Person这个名词空间管理的方法,normal_method是Person的一个属性而已。
由于normal_method在定义的时候没有指定self,所以不能完成实例对象的绑定,不能用Person().normal_method()调用。
虽然语法正确,禁止使用。
2.2类方法
>>> class Person:
... @classmethod
... def class_method(cls):
... print('class = {0.__name__} ({0})'.format(cls))
... cls.HEIGHT = 170
>>> Person.class_method()
class = Person (<class '__main__.Person'>)
>>> Person().class_method()
class = Person (<class '__main__.Person'>)
>>> print(Person.__dict__)
{
'__module__': '__main__',
'class_method': <classmethod object at 0x7fe9b1134430>,
'__dict__': <attribute '__dict__' of 'Person' objects>,
'__weakref__': <attribute '__weakref__' of 'Person' objects>,
'__doc__': None,
'HEIGHT': 170
}
NOTE:
1.在类定义中,使用@calssmethod装饰器修饰的方法
2.必须至少有一个参数,且第一个参数留给了cls,cls指代调用者即类对象自身
3.cls这个标识可以是任意合法名称,但是为了易读,请不要修改
4.通过cls可以直接操作类的属性,但是cls无法直接操作类
2.3静态方法
>>> class Person:
... @classmethod
... def class_method(cls):
... print('class = {0.__name__} ({0})'.format(cls))
... cls.HEIGHT = 170
... @staticmethod
... def staticmethod():
... print(Person.HEIGHT)
>>> Person.class_method()
class = Person (<class '__main__.Person'>)
>>> Person.staticmethod()
170
>>> print(Person.__dict__)
{
'__module__': '__main__',
'class_method': <classmethod object at 0x7f007fd74430>,
'staticmethod': <staticmethod object at 0x7f007fd746d0>,
'__dict__': <attribute '__dict__' of 'Person' objects>,
'__weakref__': <attribute '__weakref__' of 'Person' objects>,
'__doc__': None,
'HEIGHT': 170
}
NOTE:
1.在类定义中,使用@staticmethod装饰器修饰的方法
2.调用时,不会隐式的传入参数
3.静态方法,只是表明这个方法属于这个名词空间,函数归在一起,方便组织管理
2.4方法的调用
>>> class Person:
... def method(self):
... print("{}'s method".format(self))
... @classmethod
... def class_method(cls):
... print('class = {0.__name__} ({0})'.format(cls))
... cls.HEIGHT = 170
... @staticmethod
... def static_method():
... print(Person.HEIGHT)
>>> print(2,Person.class_method())
2 class = Person (<class '__main__.Person'>)
>>> print(3,Person.static_method())
3 170
>>> print(4,tom.method())
4 <__main__.Person object at 0x7f7c666dd130>'s method
>>> print(5,tom.class_method())
5 class = Person (<class '__main__.Person'>)
>>> print(6,tom.static_method())
6 170
NOTE:
1.类几乎可以调用所有内部定义的方法,但是调用普通的方法时会报错,原因是第一参数必须是类的实例
2.实例也几乎可以调用所有的方法,普通的函数调用一般不可能出现,因为不允许这样定义
3.类除了普通方法都可以调用,普通方法需要对象的实例作为第一参数
4.实例可以调用所有类中的方法(包括类方法,静态方法),普通方法传入实例自身,静态方法和类方法需要找到实例的类。
2.5 补充
>>> class Person:
... def method(self):
... print("{}'s method".format(self))
>>> tom = Person()
>>> tom.method()
<__main__.Person object at 0x7f7fd2710430>'s method
>>> Person.method()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: method() missing 1 required positional argument: 'self'
>>> Person.method(tom)
<__main__.Person object at 0x7f7fd2710430>'s method
>>> tom.__class__.method(tom)
<__main__.Person object at 0x7f7fd2710430>'s method
NOTE:
1.tom.method()调用时候,会绑定实例,调用method方法时,实例tom会注入到method中
2.Person.method(),使用类调用,不会有实例绑定,调用method方法时,缺少第一参数
网友评论