質問

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