Python:在运行时更改方法和属性

Mig*_*gol 72 python reflection runtime

我希望在Python中创建一个可以添加和删除属性和方法的类.我该怎么做呢?

哦,请不要问为什么.

Pao*_*ino 116

此示例显示将方法添加到类和实例之间的区别.

>>> class Dog():
...     def __init__(self, name):
...             self.name = name
...
>>> skip = Dog('Skip')
>>> spot = Dog('Spot')
>>> def talk(self):
...     print 'Hi, my name is ' + self.name
...
>>> Dog.talk = talk # add method to class
>>> skip.talk()
Hi, my name is Skip
>>> spot.talk()
Hi, my name is Spot
>>> del Dog.talk # remove method from class
>>> skip.talk() # won't work anymore
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: Dog instance has no attribute 'talk'
>>> import types
>>> f = types.MethodType(talk, skip, Dog)
>>> skip.talk = f # add method to specific instance
>>> skip.talk()
Hi, my name is Skip
>>> spot.talk() # won't work, since we only modified skip
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: Dog instance has no attribute 'talk'
Run Code Online (Sandbox Code Playgroud)

  • 请注意,您只能对*classes*而不是*instances*执行此操作.如果你做puppy.talk = talk,talk就不会是一个"绑定方法",也就是说,它不会得到隐含的"自我"参数. (12认同)
  • 为了增加Paul的评论:如果你想monkeypatch一个实例方法:"import types; f = types.MethodType(talk,puppy,Dog); puppy.talk = f" (10认同)
  • 非常好的编辑示例......它几乎应该用于类型模块的Python API文档,这些文档非常不合适. (8认同)
  • +1到Paolo用于演示分配和删除类方法属性的动态效果. (5认同)
  • 感谢大家好评,我更新了答案以显示差异. (3认同)

Unk*_*own 46

我希望在Python中创建一个可以添加和删除属性和方法的类.

import types

class SpecialClass(object):
    @classmethod
    def removeVariable(cls, name):
        return delattr(cls, name)

    @classmethod
    def addMethod(cls, func):
        return setattr(cls, func.__name__, types.MethodType(func, cls))

def hello(self, n):
    print n

instance = SpecialClass()
SpecialClass.addMethod(hello)

>>> SpecialClass.hello(5)
5

>>> instance.hello(6)
6

>>> SpecialClass.removeVariable("hello")

>>> instance.hello(7)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'SpecialClass' object has no attribute 'hello'

>>> SpecialClass.hello(8)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: type object 'SpecialClass' has no attribute 'hello'
Run Code Online (Sandbox Code Playgroud)

  • 请注意,这会向SpecialClass添加一个类方法.它确实*不*添加将来可用于所有SpecialClass实例的方法.(我想知道是否有办法做**.)_ (9认同)

Ale*_*lli 28

使用的一个可能有趣的替代方案types.MethodType:

>>> f = types.MethodType(talk, puppy, Dog)
>>> puppy.talk = f # add method to specific instance
Run Code Online (Sandbox Code Playgroud)

将利用函数是描述符的事实:

>>> puppy.talk = talk.__get__(puppy, Dog)
Run Code Online (Sandbox Code Playgroud)

  • 我刚学到了东西:)但我觉得它看起来不太可读. (2认同)

Rob*_*ney 5

我希望在Python中创建一个可以添加和删除属性和方法的类.我该怎么做呢?

您可以向任何类添加和删除属性和方法,它们将可用于该类的所有实例:

>>> def method1(self):
       pass

>>> def method1(self):
       print "method1"

>>> def method2(self):
       print "method2"

>>> class C():
       pass

>>> c = C()
>>> c.method()

Traceback (most recent call last):
  File "<pyshell#62>", line 1, in <module>
    c.method()
AttributeError: C instance has no attribute 'method'

>>> C.method = method1
>>> c.method()
    method1
>>> C.method = method2
>>> c.method()
    method2
>>> del C.method
>>> c.method()

Traceback (most recent call last):
  File "<pyshell#68>", line 1, in <module>
    c.method()
AttributeError: C instance has no attribute 'method'
>>> C.attribute = "foo"
>>> c.attribute
    'foo'
>>> c.attribute = "bar"
>>> c.attribute
    'bar'
Run Code Online (Sandbox Code Playgroud)


Joh*_*erg 5

您可以直接分配给该类(通过访问原始类名或通过__class__):

class a : pass
ob=a()
ob.__class__.blah=lambda self,k: (3, self,k)
ob.blah(5)
ob2=a()
ob2.blah(7)
Run Code Online (Sandbox Code Playgroud)

将打印

(3, <__main__.a instance at 0x7f18e3c345f0>, 5)
(3, <__main__.a instance at 0x7f18e3c344d0>, 7)
Run Code Online (Sandbox Code Playgroud)