If I have a python class which allows for an options parameter upon instantiation, how can I dynamically set a function to it, based upon the value of that options parameter. For example, if I have the code

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()

I get the traceback error

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
有帮助吗?

解决方案

Your functions do not define a self parameter, nor will they ever get one.

You need to use methods; you can create these from the functions by treating them as descriptors and explicitly calling .__get__() on them:

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)))

Normally, the .__get__() method is called on functions when accessing them on a class (either directly or via an instance). This doesn't happen for functions added directly on an instance however, so you need to do it manually.

其他提示

You can also use MethodType from types module.

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')
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top