python中所有东西都是对象,传统的变量、函数或者类都可以叫做变量,因此我们用属性代指传统的变量
类的属性
分类
-
实例属性
通过
self.
定义的属性覆盖同名的类属性
-
类属性
直接在类命名空间中定义的属性
通过类名可以访问和修改
通过对象只能访问,修改实际上是新增一个同名实例属性
类的方法
分为以下3种
实例方法
至少接收一个位置参数self
(这个self也可以取其他名字,约定俗成self),指向调用该方法的对象
def fun(self='None'): # 设置默认值,判断是否传入self
return self
class A(object):
def __init__(self) -> None:
self.f = fun # 不在 A 命名空间中,而在 a 命名空间
def inst_m1(self=None, *args, **kwargs):
return self
inst_m2 = fun # 这样也会变成 method
a = A()
A.m = fun # 任何添加到 A 命名空间函数都会变成 method
print(fun.__class__, fun()) # <class 'function'> None
print(a.f.__class__, a.f()) # <class 'function'> None
print(A.m.__class__, A.m()) # <class 'function'> None
print(a.m.__class__, a.m())
# <class 'method'> <__main__.A object at 0x7f51dd94d2b0>
print(a.inst_m1.__class__, a.inst_m1())
# <class 'method'> <__main__.A object at 0x7f51dd94d2b0>
print(a.inst_m2.__class__, a.inst_m2())
# <class 'method'> <__main__.A object at 0x7f51dd94d2b0>
分析
-
什么函数会变成实例方法
类命名空间中,指向函数function的变量,都会变成实例方法,无论这个函数是何时添加的
类代码块中
def
的函数、直接赋值的函数,通过类名赋值的函数,都是类命名空间中的名字但
self.f = fun
不是在类命名空间中定义的名字,而是对象命名空间(? -
method
和function
的区别 refmethod
依附于某个对象,会自动(隐式地)传入一个(第一个)位置参数:调用方法的对象本身function
不会自动传参,所有参数都显式传递
类方法
类或对象都可以调用
至少接收一个位置参数cls
(这个cls也可以取其他名字,约定俗成cls),指向调用该方法的类
class A(object):
@classmethod
def class_method(cls, *args, **kwargs):
print('class_method, cls is', cls)
a = A()
a.class_method() # class_method, cls is <class '__main__.A'>
print(a.class_method) # <bound method A.class_method of <class '__main__.A'>>
静态方法
类或对象都可以调用
class A(object):
@staticmethod
def static_method(*args, **kwargs):
print('static_method')
a = A()
a.static_method() # static_method
print(a.static_method) # <function A.static_method at 0x7f600f65adc0>
总结
bound method
(绑定方法?)都绑定了某个变量(... of <object or class>
),并且会自动(隐式)把这个变量当参数传进去,实例方法绑定一个具体实例对象self
,类方法绑定一个类cls