Python:使用 Self 并动态向对象添加方法

发布于 2024-09-24 16:02:38 字数 711 浏览 7 评论 0原文

这是我的想法:从一个简单的对象开始:

class dynamicObject(object):
    pass

并且能够动态添加预先编写的方法:

def someMethod(self):
    pass

这样我就可以做到这一点:

someObject = dyncamicObject()
someObject._someMethod = someMethod
someObject._someMethod()

问题是,它希望我指定 _someMethod() 的 self 部分,以便它看起来像这样:

someObject._someMethod(someObject)

这看起来有点奇怪,因为当一个方法“附加”到一个对象时,不是自我暗示的吗?

我对 Python 的思维方式很陌生,并且试图摆脱 C# 等语言的相同思维过程,因此这里的想法是能够通过选择我想要添加的验证方法来创建用于验证的对象它而不是建立某种对象层次结构。我认为 Python 的“自我”想法对我有利,因为我认为对象会隐式知道将自己发送到附加到它的方法中。

需要注意的一件事是,该方法没有以任何方式附加到对象(完全不同的文件),所以也许这就是问题所在?也许通过自己定义方法, self 实际上是有问题的方法,因此不能隐含为对象?

Here's my idea: Start with a simple object:

class dynamicObject(object):
    pass

And to be able to add pre written methods to it on the fly:

def someMethod(self):
    pass

So that I can do this:

someObject = dyncamicObject()
someObject._someMethod = someMethod
someObject._someMethod()

Problem is, it wants me to specify the self part of _someMethod() so that it looks like this:

someObject._someMethod(someObject)

This seems kind of odd since isn't self implied when a method is "attached" to an object?

I'm new to the Python way of thinking and am trying to get away from the same thought process for languages like C# so the idea here it to be able to create an object for validation by picking and choosing what validation methods I want to add to it rather than making some kind of object hierarchy. I figured that Python's "self" idea would work in my favor as I thought the object would implicitly know to send itself into the method attached to it.

One thing to note, the method is NOT attached to the object in any way (Completely different files) so maybe that is the issue? Maybe by defining the method on it's own, self is actually the method in question and therefore can't be implied as the object?

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

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

发布评论

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

评论(5

夜无邪 2024-10-01 16:02:38

尽管下面我试图回答字面上的问题,但我认为
穆罕默德·阿尔卡罗里的回答< /a> 更好地解决了问题实际上应该如何解决。


将方法添加到类 dynamicObject,而不是对象 someObject

class dynamicObject(object):
    pass

def someMethod(self):
    print('Hi there!')

someObject=dynamicObject()
dynamicObject.someMethod=someMethod
someObject.someMethod()
# Hi there!

当您说 someObject.someMethod=someMethod 时,则 someObject.__dict__ 获取键值对('someMethod',someMethod)

当您说 dynamicObject.someMethod=someMethod 时,someMethod 将添加到 dynamicObject__dict__ 中。您需要在类中定义 someMethod
someObject.someMethod 充当方法调用。有关这方面的更多信息,请参阅 Raymond Hettinger 的关于描述符的文章——毕竟,方法只不过是一个描述符! -- 以及 Shalabh Chaturvedi 的关于属性查找的文章


还有一种替代方法:

import types
someObject.someMethod=types.MethodType(someMethod,someObject,type(someObject))

但这确实令人厌恶,因为您将 'someMethod' 定义为 someObject.__dict__ 中的键,这不是方法的正确位置。事实上,你根本没有得到一个类方法,只是一个柯里化函数。这不仅仅是一个技术问题。 DynamicObject 的子类将无法继承 someMethod 函数。

Although below I've tried to answer the literal question, I think
Muhammad Alkarouri's answer better addresses how the problem should actually be solved.


Add the method to the class, dynamicObject, rather than the object, someObject:

class dynamicObject(object):
    pass

def someMethod(self):
    print('Hi there!')

someObject=dynamicObject()
dynamicObject.someMethod=someMethod
someObject.someMethod()
# Hi there!

When you say someObject.someMethod=someMethod, then someObject.__dict__ gets the key-value pair ('someMethod',someMethod).

When you say dynamicObject.someMethod=someMethod, then someMethod is added to dynamicObject's __dict__. You need someMethod defined in the class for
someObject.someMethod to act like a method call. For more information about this, see Raymond Hettinger's essay on descriptors -- after all, a method is nothing more than a descriptor! -- and Shalabh Chaturvedi's essay on attribute lookup.


There is an alternative way:

import types
someObject.someMethod=types.MethodType(someMethod,someObject,type(someObject))

but this is really an abomination since you are defining 'someMethod' as a key in someObject.__dict__, which is not the right place for methods. In fact, you do not get a class method at all, just a curried function. This is more than a mere technicality. Subclasses of dynamicObject would fail to inherit the someMethod function.

听风吹 2024-10-01 16:02:38

为了实现你想要的(通过选择我想要添加的验证方法来创建一个用于验证的对象),更好的方法是:

class DynamicObject(object):
    def __init__(self, verify_method = None):
        self.verifier = verify_method
    def verify(self):
        self.verifier(self)

def verify1(self):
    print "verify1"

def verify2(self):
    print "verify2"

obj1 = DynamicObject()
obj1.verifier = verify1

obj2 = DynamicObject(verify2)
#equivalent to
#obj2 = DynamicObject()
#obj2.verify = verify2

obj1.verify()
obj2.verify()

To achieve what you want (create an object for validation by picking and choosing what validation methods I want to add to it), a better way is:

class DynamicObject(object):
    def __init__(self, verify_method = None):
        self.verifier = verify_method
    def verify(self):
        self.verifier(self)

def verify1(self):
    print "verify1"

def verify2(self):
    print "verify2"

obj1 = DynamicObject()
obj1.verifier = verify1

obj2 = DynamicObject(verify2)
#equivalent to
#obj2 = DynamicObject()
#obj2.verify = verify2

obj1.verify()
obj2.verify()
懒的傷心 2024-10-01 16:02:38

为什么不使用setattr?我发现这种方式更加明确。

class dynamicObject(object):
    pass

def method():
    print "Hi"

someObject = dynamicObject()
setattr(someObject,"method", method)
someObject.method()

Why don't you use setattr? I found this way much more explicit.

class dynamicObject(object):
    pass

def method():
    print "Hi"

someObject = dynamicObject()
setattr(someObject,"method", method)
someObject.method()
哑剧 2024-10-01 16:02:38

有时,当方法很简单时,需要编写一个常规函数并在之后添加它,这很烦人。在这种情况下,lambda 可以来救援:

    class Square:
        pass

    Square.getX = lambda self: self.x
    Square.getY = lambda self: self.y
    Square.calculateArea = lambda self: self.getX() * self.getY()

希望这会有所帮助。

Sometimes it is annoying to need to write a regular function and add it afterwards when the method is very simple. In that case, lambdas can come to the rescue:

    class Square:
        pass

    Square.getX = lambda self: self.x
    Square.getY = lambda self: self.y
    Square.calculateArea = lambda self: self.getX() * self.getY()

Hope this helps.

情泪▽动烟 2024-10-01 16:02:38

如果您只想包装另一个类,而不必处理为任何实例分配新方法,则可以将相关方法设为该类的静态方法:

class wrapperClass(object):
    @staticmethod
    def foo():
        print("yay!")

obj = wrapperClass()
obj.foo()  // Yay!

然后您可以为任何其他类提供 。 foo 方法具有多重继承。

class fooDict(dict, wrapperClass):
    """Normal dict with foo method"""

foo_dict = fooDict()
foo_dict.setdefault('A', 10)
print(foo_dict)   // {'A': 10}
foo_dict.foo()    // Yay!

If you just want to wrap another class, and not have to deal with assigning a new method to any instance, you can just make the method in question a staticmethod of the class:

class wrapperClass(object):
    @staticmethod
    def foo():
        print("yay!")

obj = wrapperClass()
obj.foo()  // Yay!

And you can then give any other class the .foo method with multiple inheritance.

class fooDict(dict, wrapperClass):
    """Normal dict with foo method"""

foo_dict = fooDict()
foo_dict.setdefault('A', 10)
print(foo_dict)   // {'A': 10}
foo_dict.foo()    // Yay!
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文