2

如果我有一个允许在实例化时使用选项参数的 python 类,我如何根据该选项参数的值为其动态设置一个函数。例如,如果我有代码

def hello1():
    print(self.name,"says hi")

def hello2():
    print(self.name,"says hello")

class A:
    def __init__(self, name, opt=0):
        if opt == 1:
            setattr(self,'hello',hello1)
        else:
            setattr(self,'hello',hello2)

if __name__ == "__main__":
    a1 = A("my")
    a2 = A("name",1)
    a1.hello()
    a2.hello()

我得到回溯错误

Traceback (most recent call last):
  File "dynamic_classes.py", line 17, in <module>
    a1.hello()
  File "dynamic_classes.py", line 5, in hello2
    print(self.name,"says hello")
NameError: global name 'self' is not defined
4

2 回答 2

5

您的函数没有定义self参数,也不会得到一个参数。

你需要使用方法;您可以通过将它们视为描述符并显式调用它们来从函数中创建.__get__()它们:

def hello1(self):
    print(self.name,"says hi")

def hello2(self):
    print(self.name,"says hello")

class A:
    def __init__(self, name, opt=0):
        if opt == 1:
            setattr(self, 'hello', hello1.__get__(self, type(self))
        else:
            setattr(self, 'hello', hello2.__get__(self, type(self)))

通常,在上(直接或通过实例).__get__()访问函数时,会在函数上调用该方法。但是,直接在实例上添加的函数不会发生这种情况,因此您需要手动完成。

于 2013-08-06T21:50:27.350 回答
0

您还可以使用类型模块中的 MethodType。

import types

def hello1(self):
   print(self.name,"says hi")

def hello2(self):
   print(self.name,"says hello")

class A:
   def __init__(self, name, opt=0):
       self.name = name
       if opt == 1:
           self.hello = types.MethodType(hello1, self)
       else:
           self.hello = types.MethodType(hello2, self)

A('a').hello()   # ('a', 'says hello')

A('a', 1).hello() # ('a', 'says hi')
于 2017-02-20T19:28:47.667 回答