Python:Hack 对不属于其类的对象调用方法

发布于 2024-09-01 07:06:24 字数 605 浏览 3 评论 0原文

假设您定义了一个类,其中有一个执行一些复杂处理的方法:

class A(object):
    def my_method(self):
        # Some complicated processing is done here
        return self

现在您希望完全在另一个类的某个对象上使用该方法。例如,您想要执行 A.my_method(7)

这就是您会得到的结果:TypeError: unbound method my_method() can be called with A instance as first argument (got int instancerather)

现在,是否有可能破解一些东西,以便您可以在7上调用该方法?我想避免移动函数或重写它。 (请注意,该方法的逻辑确实取决于 self。)

需要注意的是:我知道有些人会想说,“你做错了!你正在滥用 Python!你不应该做吧!”所以,是的,我知道,这是我想做的一件可怕的事情。我问的是是否有人知道如何去做,而不是如何告诉我我不应该这样做。

Assume you define a class, which has a method which does some complicated processing:

class A(object):
    def my_method(self):
        # Some complicated processing is done here
        return self

And now you want to use that method on some object from another class entirely. Like, you want to do A.my_method(7).

This is what you'd get: TypeError: unbound method my_method() must be called with A instance as first argument (got int instance instead).

Now, is there any possibility to hack things so you could call that method on 7? I'd want to avoid moving the function or rewriting it. (Note that the method's logic does depend on self.)

One note: I know that some people will want to say, "You're doing it wrong! You're abusing Python! You shouldn't do it!" So yes, I know, this is a terrible terrible thing I want to do. I'm asking if someone knows how to do it, not how to preach to me that I shouldn't do it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

浴红衣 2024-09-08 07:06:25

您可以将该方法放入需要调用它的两个对象的超类中,不是吗?如果它如此重要以至于您无法复制它,也无法将其更改为不使用 self,那么这是我能看到的唯一其他选项。

You could just put that method into a superclass of the two objects that need to call it, couldn't you? If its so critical that you can't copy it, nor can you change it to not use self, thats the only other option I can see.

天气好吗我好吗 2024-09-08 07:06:25
>>> class A():
...     me = 'i am A'
... 
>>> class B():
...     me = 'i am B'
... 
>>> def get_name(self):
...     print self.me
... 
>>> A.name = get_name
>>> a=A()
>>> a.name()
i am A
>>> 
>>> B.name = get_name
>>> b=B()
>>> b.name()
i am B
>>> 
>>> class A():
...     me = 'i am A'
... 
>>> class B():
...     me = 'i am B'
... 
>>> def get_name(self):
...     print self.me
... 
>>> A.name = get_name
>>> a=A()
>>> a.name()
i am A
>>> 
>>> B.name = get_name
>>> b=B()
>>> b.name()
i am B
>>> 
慕巷 2024-09-08 07:06:25

为什么你不能这样做

class A(object):
    def my_method(self,arg=None):
        if (arg!=None):
           #Do Some Complicated Processing with both objects and return something 
        else:
               # Some complicated processing is done here
        return self

Why cant you do this

class A(object):
    def my_method(self,arg=None):
        if (arg!=None):
           #Do Some Complicated Processing with both objects and return something 
        else:
               # Some complicated processing is done here
        return self
∞梦里开花 2024-09-08 07:06:25

在 Python 中,函数不需要包含在类中。听起来你需要的是实用函数,所以只需这样定义它:

def my_function(object):
    # Some complicated processing is done here
    return object

my_function(7)
my_function("Seven")

只要你的处理使用通过 的魔力传递给 my_function 的所有对象上可用的方法和属性鸭子打字一切都会正常工作。

In Python functions are not required to be enclosed in classes. It sounds like what you need is utility function, so just define it as such:

def my_function(object):
    # Some complicated processing is done here
    return object

my_function(7)
my_function("Seven")

As long as your processing is using methods and attribute available on all objects that you pass to my_function through the magic of duck typing everything will work fine.

╰ゝ天使的微笑 2024-09-08 07:06:25

这就是所谓的staticmethod

class A(object):
    @staticmethod
    def my_method(a, b, c):
        return a, b, c

但是在staticmethods 中,您不会获得对self 的引用。

如果您想要引用class而不是instance(实例意味着引用self),您可以使用类方法:

class A(object):
    classvar = "var"

    @classmethod
    def my_method(cls, a, b, c):
        print cls.classvar
        return a, b, c

但是您只能访问类变量,而不能访问实例变量(通常在 __init__ 构造函数内创建/定义的变量)。

如果这还不够好,那么您将需要以某种方式传递“绑定”方法或将“self”传递到方法中,如下所示:

class A(object):
    def my_method(self):
        # use self and manipulate the object

inst = A()
A.my_method(inst)

正如有些人已经说过的,从一个类继承另一个类并不是一个坏主意:

class A(object):
    ... methods ...

class B(A):
    def my_method(self):
        ... use self

newA = B()

That's what's called a staticmethod:

class A(object):
    @staticmethod
    def my_method(a, b, c):
        return a, b, c

However in staticmethods, you do not get a reference to self.

If you'd like a reference to the class not the instance (instance implies reference to self), you can use a classmethod:

class A(object):
    classvar = "var"

    @classmethod
    def my_method(cls, a, b, c):
        print cls.classvar
        return a, b, c

But you'll only get access to class variables, not to instance variables (those typically created/defined inside the __init__ constructor).

If that's not good enough, then you will need to somehow pass a "bound" method or pass "self" into the method like so:

class A(object):
    def my_method(self):
        # use self and manipulate the object

inst = A()
A.my_method(inst)

As some people have already said, it's not a bad idea to just inherit one class from the other:

class A(object):
    ... methods ...

class B(A):
    def my_method(self):
        ... use self

newA = B()
酒儿 2024-09-08 07:06:24

当然,我不建议在实际代码中执行此操作,但是,当然,您可以到达类内部并将其方法用作函数:

class A(object):
    def my_method(self):
        # Some complicated processing is done here
        return 'Hi'

print(A.__dict__['my_method'](7))
# Hi

Of course I wouldn't recommend doing this in real code, but yes, sure, you can reach inside of classes and use its methods as functions:

class A(object):
    def my_method(self):
        # Some complicated processing is done here
        return 'Hi'

print(A.__dict__['my_method'](7))
# Hi
七颜 2024-09-08 07:06:24

你不能。实际上,Python 3000 中已经取消了该限制,但我认为您没有使用它。

然而,为什么你不能做这样的事情:

def method_implementation(self, x,y):
   # do whatever

class A():
   def method(self, x, y):
        return method_implementation(self, x, y)

如果你真的想滥用Python,那么编写一个实现该行为的描述符类。请

class Hack:
   def __init__(self, fn):
       self.fn = fn
   def __get__(self, obj, cls):
       if obj is None: # called staticly
            return self.fn
       else:
            def inner(*args, **kwargs):
                 return self.fn(obj, *args, **kwargs)
            return inner

注意,这完全未经测试,可能会破坏一些极端情况,并且都是邪恶的。

You can't. The restriction has actually been lifted in Python 3000, but I presume you are not using that.

However, why can't you do something like:

def method_implementation(self, x,y):
   # do whatever

class A():
   def method(self, x, y):
        return method_implementation(self, x, y)

If you are really in the mood for python abuse, write a descriptor class that implements the behavior. Something like

class Hack:
   def __init__(self, fn):
       self.fn = fn
   def __get__(self, obj, cls):
       if obj is None: # called staticly
            return self.fn
       else:
            def inner(*args, **kwargs):
                 return self.fn(obj, *args, **kwargs)
            return inner

Note that this is completely untested, will probably break some corner cases, and is all around evil.

谁的年少不轻狂 2024-09-08 07:06:24
def some_method(self):
    # Some complicated processing is done here
    return self

class A(object):
    my_method = some_method
a = A()

print some_method
print a.my_method
print A.my_method
print A.my_method.im_func
print A.__dict__['my_method']

prints:

<function some_method at 0x719f0>
<bound method A.some_method of <__main__.A object at 0x757b0>>
<unbound method A.some_method>
<function some_method at 0x719f0>
<function some_method at 0x719f0>

听起来您正在类上查找方法并获取未绑定方法未绑定方法需要适当类型的对象作为第一个参数。

如果您想将函数作为函数应用,则必须获取它的函数版本的句柄。

def some_method(self):
    # Some complicated processing is done here
    return self

class A(object):
    my_method = some_method
a = A()

print some_method
print a.my_method
print A.my_method
print A.my_method.im_func
print A.__dict__['my_method']

prints:

<function some_method at 0x719f0>
<bound method A.some_method of <__main__.A object at 0x757b0>>
<unbound method A.some_method>
<function some_method at 0x719f0>
<function some_method at 0x719f0>

It sounds like you're looking up a method on a class and getting an unbound method. An unbound method expects a object of the appropriate type as the first argument.

If you want to apply the function as a function, you've got to get a handle to the function version of it instead.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文