Python: использование Self и добавление методов к объекту на лету - PullRequest
3 голосов
/ 22 сентября 2010

Вот моя идея: начать с простого объекта:

class dynamicObject(object):
    pass

И чтобы иметь возможность добавлять заранее написанные методы к нему на лету:

def someMethod(self):
    pass

Так что я могу сделать это:

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

Проблема в том, что мне нужно указать собственную часть _someMethod (), чтобы она выглядела следующим образом:

someObject._someMethod(someObject)

Это кажется странным, поскольку не подразумевается, что метод "привязан" к объекту?

Я новичок в мышлении Python и пытаюсь уйти от того же мыслительного процесса для языков, как C #, поэтому идея здесь в том, чтобы иметь возможность создавать объект для проверки, выбирая и выбирая, какие методы проверки я хочу добавить к нему, а не делать какую-то иерархию объектов. Я подумал, что идея «я» Python будет работать в мою пользу, так как я думал, что объект будет неявно знать, чтобы отправить себя в метод, присоединенный к нему.

Следует отметить, что метод НЕ привязан к объекту каким-либо образом (совершенно разные файлы), так что, может быть, в этом проблема? Может быть, определяя метод самостоятельно, на самом деле self - это рассматриваемый метод и, следовательно, не может подразумеваться как объект?

Ответы [ 5 ]

6 голосов
/ 22 сентября 2010

Чтобы достичь того, что вы хотите ( создать объект для проверки, выбрав и выбрав, какие методы проверки я хочу добавить к нему ), лучший способ:

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()
6 голосов
/ 22 сентября 2010

Хотя ниже я попытался ответить на буквальный вопрос, я думаю, ответ Мухаммеда Алкарури лучше описывает, как на самом деле должна быть решена проблема.


Добавьте метод ккласс, 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 действовал как вызов метода.Для получения дополнительной информации об этом см. Эссе Раймонда Хеттингера о дескрипторах - в конце концов, метод - это не более чем дескриптор!- и эссе Шалаба Чатурведи о поиске атрибутов .


Существует альтернативный способ:

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

, но это действительно мерзость, поскольку вы определяете'someMethod' как ключ в someObject.__dict__, что не место для методов.На самом деле, вы вообще не получаете метод класса, только каррированную функцию.Это больше, чем просто техническаяПодклассы dynamicObject не смогут унаследовать функцию someMethod.

0 голосов
/ 26 января 2017

Если вы просто хотите обернуть другой класс, и вам не нужно присваивать новый метод какому-либо экземпляру, вы можете просто сделать этот метод статическим методом класса:

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!
0 голосов
/ 22 сентября 2010

Иногда раздражает необходимость писать обычную функцию и добавлять ее потом, когда метод очень прост.В этом случае на помощь могут прийти лямбды:

    class Square:
        pass

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

Надеюсь, это поможет.

0 голосов
/ 22 сентября 2010

Почему вы не используете setattr? Я нашел этот способ гораздо более явным.

class dynamicObject(object):
    pass

def method():
    print "Hi"

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