Python 绑定方法与非绑定方法详解
一、绑定方法
1. 绑定方法的定义:凡是类中的方法或函数,默认情况下都是绑定给对象使用的。
-
类中不被任何装饰器装 装饰的方法或函数,默认情况下都是绑定给对象使用的,例如 def fun() 或 def fun(self)
-
用@classmethod装饰的方法是绑定到类上的
-
用@staticmethod修饰的方法,是解除所有绑定关系作为普通函数存在,为非绑定方法
2. 绑定方法的特点:
-
其特点是「调用方」本身自动作为第一个参数传入。
-
一个方法绑定到谁身上,谁来调用,该调用者当作第一个参数会自动传参。
-
绑定给对象:调用方是一个「对象」,该对象自动传入(调用方是『类』,需要手动传入第一个参数)
-
绑定给类:调用方是「类|对象」,该类自动传入
3. 绑定方法的分类:
-
绑定到类的方法:
-
用classmethod装饰器装饰的方法就是类绑定方法(「对象」也可调用「类绑定方法」,但仍将类当作第一个参数传入)。
-
类.boud_method(),自动将「类」当作第一个参数传入
-
对象.boud_method(),自动将「类」当作第一个参数传入
-
绑定到对象的方法:
-
没有被任何装饰器装饰的方法,默认是绑定给对象使用的方法。
-
对象.boud_method(args2,args3),自动将“对象”当作第一个参数传入。
-
类.boud_method(args1,args2,args3),需按照参数规则一一传递所有参数
-- “类”可以调用“对象的绑定方法”,但不会自动传值,需按照参数规则一一传递所有参数
二、 非绑定方法:
1. 非绑定方法的定义:在类内部用@staticmethod装饰的函数即「非绑定方法」,就是普通函数。
2. 非绑定方法的特点:
-
不与类或对象绑定
-
没有自动传参的效果
-
『类和对象』都可以调用
-
不管谁来调用,都不会自动传值
3. 【答疑】
-
自由方法应该也算非绑定方法?-- 自由方法是对象的绑定方法,绑定给对象。
-
如果定义staticmethod时传self或cls,还算是非绑定方法吗?
-- 在静态方法里面 访问不了 类或者实例 的任何属性。 一般不需要传参数self
【注意】在类中直接定义的函数,没有被任何装饰器装饰的,都是绑定到对象的方法,不是普通函数,对象调用该方法会自动传值
三、总结:
当「对象」调用「对象的绑定方法」时,默认把对象自己当做第一个参数传递到函数中
当 「类」 调用「对象的绑定方法」时,不会进行自动传值的;也就是说,函数有几个参数,我们就得传递进去几个参数。
当「类|对象」在调用「类的绑定方法」时,会默认把 类 当作参数传递进去。
当「类|对象」在调用「非绑定方法」时,不会自动传值
四、代码示例
# 对象的绑定方法 # 当“对象” 调用对象的绑定方法时,会默认把 对象当作 第一个参数传递进去. # 当 “类” 调用对象的绑定方法时,不会默认传参,需要一一传参 class People: def __init__(self,name): self.name = name # 对象的绑定方法 def object_has_args(self): # 这是对象的绑定方法 print("Here is 'object_has_args'") def object_no_args(): # 这也是对象的绑定方法 print("Here is 'object_no_args'") p = People('xiaohua') # 对象的绑定方法:有参数+无参数 # >>>>>>类中无任何装饰器的方法或函数,默认情况下都是绑定给对象使用的,例如 def f() 或 def f(self) <<<<< print(p.object_has_args) # <bound method People.talk of <__main__.People object at xxxxx print(p.object_no_args) # <bound method People.talk of <__main__.People object at xxxxx p.object_has_args() # 对象来调用,仅仅是当作函数使用 p.object_no_args() # 报错,这里会传参对象p给函数;takes 0 positional arguments but 1 was given print(People.object_no_args) # <function People.object_no_args at 0x7f874422c040> print(People.object_has_args) # <function People.object_no_args at 0x7f874422c040> People.object_no_args() # 类来调用,仅仅是当作函数使用 People.object_has_args("需要手动传参") # 对比测试 People.object_has_args() # 报错,类调用方法时,不会自动传参;missing 1 required positional argument: 'self'
# 调用类的绑定方法时,会默认把类当作参数传递进去. class People: def __init__(self,name): self.name = name # 类的绑定方法 @classmethod def classmethod_has_args(cls): print("有参数") @classmethod def classmethod_no_args(): print("无参数") p = People('xiaohua') # 类的绑定方法:有参数+无参数 # >>>>>>>>当「对象|类」在调用类的绑定方法时,会默认把类当作参数传递进去<<<<<<<< p.classmethod_has_args() # 类的绑定方法:当对象在调用类的绑定方法时,也会默认把类当作参数传递进去 People.classmethod_has_args() # 类的绑定方法:默认把『类』当做第一个参数传入 p.classmethod_no_args() # 报错,takes 0 positional arguments but 1 was given People.classmethod_no_args() # 报错,takes 0 positional arguments but 1 was given print(People.classmethod_has_args) # 类的绑定方法:<bound method People.talk of <class '__main__.People'>> print(p.classmethod_has_args) # 类的绑定方法:<bound method People.talk of <class '__main__.People'>> print(p.classmethod_no_args) # 类的绑定方法:<bound method People.talk of <class '__main__.People'>> print(People.classmethod_no_args) # 类的绑定方法:<bound method People.talk of <class '__main__.People'>>
# 非绑定方法:遵从函数参数传递规则,有几个参数就传递几个参数 class People: def __init__(self,name): self.name = name # 非绑定方法 @staticmethod def staticmethod_no_args(): print('xx') @staticmethod def staticmethod_has_args(stm): print(f"Here is: {stm}") p = People('xiaohua') # 非绑定方法:有几个参数就传递几个参数 print(p.staticmethod_has_args) print(People.staticmethod_has_args) print(p.staticmethod_no_args) print(People.staticmethod_no_args,"\n") p.staticmethod_no_args() # People.staticmethod_no_args() p.staticmethod_has_args("对象") People.staticmethod_has_args("类") # ''' <function People.staticmethod_has_args at 0x7fb06a22b160> <function People.staticmethod_has_args at 0x7fb06a22b160> <function People.staticmethod_no_args at 0x7fb06a22b040> <function People.staticmethod_no_args at 0x7fb06a22b040> xx xx Here is: 对象 Here is: 类 '''