zoukankan      html  css  js  c++  java
  • 23.绑定方法和非绑定方法

    绑定和方法调用

    1、首先,方法仅仅是类内部定义的函数。(这意味着方法是类属性而不是实例属性)
    2、其次,方法只有在其所属的类拥有实例时,才能被调用。当存在一个实例时,方法才被认为是绑定到那个实例了。没有实例时方法就是未绑定的
    3、最后,任何一个方法定义中的第一个参数都是变量 self,它表示调用此方法的实例对象

    核心笔记:self 是什么?

    1、self 变量用于在类实例方法中引用方法所绑定的实例。
    
    2、因为方法的实例在任何方法调用中总是作为第一个参数传递的,self 被选中用来代表实例。
    
    3、你必须在方法声明中放上 self(你可能已经注意到了这点),但可以在方法中不使用实例(self)。
    
    4、如果你的方法中没有用到 self , 那么请考虑创建一个常规函数,除非你有特别的原因。
    
    5、毕竟,你的方法代码没有使用实例,没有与类关联其功能,这使得它看起来更像一个常规函数
    
    某个对象调用其方法时,python解释器会把这个对象作为第一个参数传递给self,所以开发者只需要传递后面的参数即可

    Bound Method和Unbound Method

    在Python中,当对作为属性的函数进行引用时,会有两种形式,一种称为Bound Method,这种形式是通过类的实例对象进行属性引用,而另一种则是通过类进行属性引用,称为Unbound Method

    例子:

    #!/usr/bin/env python
    #coding:utf8
    
    
    class A(object):
        def g(self, value):
            self.value = value
            print(self.value)
    
    
    a = A()
    A.g(a, 10)

    在Python中,在对Unbound Method尽心调用时,我们必须显示地提供一个instance对象作为函数的第一个位置参数,因为g无论如何都需要一个self参数。所以才会有A.g(a, 10)这样的形式。而无论是对Unbound Method进行调用,还是对bound Method进行调用,Python虚拟机的动作在本质上都是一样的,都是调用带位置参数的一般函数,区别只在于:当调用Bound Method时,Python虚拟机帮我们完成了PyFunctionObject对象和instance对象的绑定,instance对象将自动成为self参数,而调用Unbound Method时,则没有这个绑定,需要我们自己传入self参数

    bound和unbound方法是个很简单的概念。在许多语言当中,类似于a.b()这样的调用方法是一个整体,但在Python中,它其实是两部分:获取属性a.b,调用()。所以也可以写成:

    c = a.b
    c()

    跟直接调用a.b()是等效的。当a是某个类的实例,b是这个类的方法的时候,a.b的返回值就是bound method,也就是绑定方法。它实际上是个bound method对象,这个对象提前将self参数进行了绑定。实际演示一下就很容易懂了:

    例如:在python2中

    #!/usr/bin/env python
    #coding:utf8
    
    
    class A(object):
        def b(self):
            pass
    
    a = A()
    print a.b
    print A.b

    执行结果:

    <bound method A.b of <__main__.A object at 0x00000000031534E0>>
    <unbound method A.b>

    在python3中:

    #!/usr/bin/env python
    #coding:utf8
    
    
    class A(object):
        def b(self):
            pass
    
    a = A()
    print(a.b)
    print(A.b)

    执行结果:

    <bound method A.b of <__main__.A object at 0x0000028D2613C320>>
    <function A.b at 0x0000028D2620B8C8>
    相应的unbound method是没有绑定self的对象。在Python 3中,它就是普通的函数,在Python 2中则是unbound method类型,不过区别不大。
    我们知道像A.b这样的方法实际上跟一个普通定义的函数没有本质区别,这个函数有一个参数self,所以实际上完全可以用A.b(a)的方式来调用,也就是手工将self参数指定为a。这也就是unbound method的用法。而相应的,bound method是一个实现了__call__的对象,它自动将调用这个对象的过程重定向到A.b(a)上面,相当于通过functools.partial绑定了第一个参数的效果,所以叫做bound method。


    我们可以认为:当通过类来获取方法的时候,得到的是非绑定方法对象;当通过实例来获取方法的时候,得到的是绑定方法对象

    调用绑定方法和非绑定方法

    方法只有在其所属的类拥有实例时,才能被调用。当存在一个实例时,方法才被认为是绑定到那个实例了。没有实例时方法就是未绑定的。当没有实例并且需要调用一个非绑定方法的时候,则必须传递self 参数。
    调用非绑定方法并不经常用到,主要应用场景:你在派生一个子类 ,而且你要覆盖父类的方法,这时你需要调用哪个父类中想要覆盖的构造方法。

     例子:调用非绑定方法

    #!/usr/bin/env python
    #coding:utf8
    
    
    class Foo(object):
        def __init__(self,name,sex,age):
            self.name=name
            self.sex=sex
            self.age=age
        def show(self):
            print "name is %s,sex is %s"%(self.name,self.sex)
    
    class Bar(Foo):
        def __init__(self,name,sex,age,id,salary):
            super(Bar,self).__init__(name,sex,age) #这就是在调用父类非绑定方法
            #或者Foo.__init__(self,name,sex,age)  现在不用了
            self.id=id
            self.salary=salary
    
        def info(self):
            print "name is %s salary is %s"%(self.name,self.salary)
    
    f = Bar('cmustard', 'F', 22, 123123, 1000)
    f.show()
    f.info()

    使用super()的漂亮之处在于,不需要明确提供父类。这意味着如果改变了类继承关系,只需要改一行代码(class 语句本身)而不必在大量代码中去查找所有被修改的那个类的名字。

    执行结果:

    name is cmustard,sex is F
    name is cmustard salary is 1000

    Bar是Foo子类,我们重载了构造器__init__()

    我们通过父类名来调用它,并且传递给它 self 和其他所需要的参数。一旦调用返回,我们就能定义那些与父类不同的仅存在我们的子类中的实例定制 。

    链接:https://www.zhihu.com/question/41006598/answer/148994582
    https://www.cnblogs.com/cmustard/p/6769933.html
  • 相关阅读:
    [HEOI2016/TJOI2016]树
    [BJOI2018]求和
    洛谷P5002 专心OI
    [GDOI2014]采集资源
    小凯的数字
    APP微信支付
    java对接支付宝支付
    layui 视频上传本地(项目)
    mybatis Generator生成代码及使用方式
    Java IO流学习总结
  • 原文地址:https://www.cnblogs.com/zhongguiyao/p/11048692.html
Copyright © 2011-2022 走看看