Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
python方法窃取器_Python_Oop - Fatal编程技术网

python方法窃取器

python方法窃取器,python,oop,Python,Oop,如何从一个类“窃取”或将方法复制到另一个类上 示例代码: class A(object): def foo(self): print "blah" class B(object): foo = A.foo B().foo() 预期产出: "blah" 相反: TypeError:必须使用以下实例调用未绑定的方法foo() 第一个参数(没有得到任何结果) 你可以在这里用。继承允许您基于另一个对象创建对象,继承其所有函数和属性 在本例中,它看起来像: class A(obj

如何从一个类“窃取”或将方法复制到另一个类上

示例代码:

class A(object):
  def foo(self):
    print "blah"


class B(object):
  foo = A.foo

B().foo()
预期产出:

"blah"
相反:

TypeError:必须使用以下实例调用未绑定的方法foo() 第一个参数(没有得到任何结果)

你可以在这里用。继承允许您基于另一个对象创建对象,继承其所有函数和属性

在本例中,它看起来像:

class A(object):
  def foo(self):
    print "blah"


class B(A):
  # You can add new methods or attributes here,
  #  or even overwrite those inherited from A if you
  #  really want to, though you have to be careful with that.
  pass
在该声明之后

>>> B().foo()
"blah"
这是因为:

  • 您创建了类
    A
    ,并为其创建了方法
    foo
  • 您创建了类
    B
    继承自
    A
    ,这意味着当
    A
    生下它时,
    B
    A
    所拥有的一切一起诞生。
    • 在我们的例子中,
      B
      A
      的精确副本,因为我们没有对它做任何其他操作。但是,我们可以进行更改或添加更多方法
例如:

class A(object):
    def foo(self):
        print "blah"

class B(A):
   def newfoo(self):
       print "class A can't do this!"
在使用中,我们会看到:

>>> A().foo()
blah
>>> B().foo()
blah
>>> A().newfoo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'A' object has no attribute 'newfoo'
>>> B().newfoo()
class A can't do this!
而不是

class B(object):
    foo = A().foo

当您在没有
()
的情况下编写
A.foo
时,您直接从
A
类型请求方法,这在Python中不起作用。如果要执行
foo=A().foo
,您要做的是实例化
A
对象,然后获取其方法的副本
foo
,然后分配它

使用
\uuuu func\uuu

>>> A.foo
<unbound method A.foo>
>>> A.foo.__func__
<function foo at 0x00BC5F70>
>>> class B(object):
...   foo = A.foo.__func__
...
>>> B().foo()
"blah"
>A.foo
>>>A.foo.\u func__
>>>B类(对象):
...   foo=A.foo.\uu func__
...
>>>B().foo()
“废话”
引述:

实例方法对象组合了类、类实例和任何可调用对象(通常是用户定义的函数)

特殊只读属性:_self__;为类实例对象,_func__;为函数对象__doc是方法的文档(与函数相同)__名称是方法名称(与函数名称相同)__module_uu是在其中定义方法的模块的名称,如果不可用,则为None


这里的问题是,您试图窃取的是绑定方法,但是,您的示例不涉及使用实例状态(
self
)的函数。因此,您有两个即时选项:

  • A.foo
    的定义设为静态方法(
    @staticmethod
    decorator)
  • 修饰或包装函数以传递未使用的参数。例如,使用
    functools
  • 例如

    这是因为您的方法不使用实例状态,并且不需要创建子类

    为了进一步修饰,绑定实例方法(如
    a.foo
    )需要一个绑定实例参数(
    self
    ,其中self是
    a
    的实例)。在正常使用中,第一个参数会自动传递:

    a = A()
    
    现在:

    …两者都是等价的。在第一种情况下,语法
    instance.bound_method()
    从词汇角度推断
    InstanceClass.bound_method(instance)
    instance
    解析为
    self
    )。这就是调用
    A.foo()
    将导致错误的原因,因为它需要
    A
    的实例


    上面的解决方案是将函数扭曲成一个将
    None
    作为实例传递的函数,因为无论如何都不会使用实例(没有基于状态的逻辑)。在使用staticmethod的情况下,它删除了第一个隐含的预期绑定实例参数
    self

    ,因为未绑定的方法已被删除(参见Guido van Rossum的)

    但是请注意,unbound方法是一个函数包装器,用于隐式检查第一个传递的参数是否是定义该方法的类的实例,这是该方法的一个先决条件,通常不应违反该先决条件。错误消息为您提供了正确的解决方案,即继承:

    B(A)类:
    通过
    
    一般来说,您不应该从非基类窃取方法,因为它将中断非基类中的
    super()
    调用(简称
    super(\uuuu class\uuuuu,self)
    )。事实上,该计划:

    A类(对象):
    def foo(self):
    打印“废话”
    super()。\uuuu init\uuuuu()
    B类(对象):
    foo=A.foo.\uu func__
    B().foo()
    
    提出:

    TypeError: super(type, obj): obj must be an instance or subtype of type
    

    这是因为
    super(\uuuuu class\uuuuuu,self)
    首先检查
    self
    是否是
    \uuuuu class\uuuuuuuu
    的实例(或子类型),即
    A
    。但是您传递了一个
    B
    实例,并且
    B
    不是
    a
    的子类。因此Python2 unbound方法的错误消息是有用的。

    如果
    foo
    是类方法而不是实例方法,这将更有意义。或者,他也可以只做
    a().foo
    而不是
    a.foo.\uu func\ucode>@jdotjdot
    a()。foo
    是一个“绑定方法”,绑定到
    A
    的特定实例。在(可能是简化的)示例中,这并不重要,因为它不使用
    self
    ,也可以用静态/类方法代替,但在更复杂的场景中它会。我假设OP的意图,尽管没有说明,是从任意类中选择一个有用的方法(也就是说,不打算从中继承,也不是混入),并在他自己的类中拥有相同的方法,但引用/操作他的类的实例,而不是原始类的实例。你是对的。我在考虑这个具体的例子,因为不需要
    self
    ,但你肯定是对的,在一般情况下,
    A().foo
    不是一个好的调用。
    a = A()
    
    a.foo()
    A.foo(a)
    
    TypeError: super(type, obj): obj must be an instance or subtype of type