简体   繁体   中英

Assigning attributes to class methods

Suppose I have a class that acts as a method container. I have a config file that lists those methods in a dictionary. In a program, I want to import the dictionary from config and iterate over it, calling methods from that class as I go.

The issue is that I need to have them be handled one way if the method is of one kind, and another way if another. So the container class looks like:

class Circus(object):
    def clown(self):
        return print("*HONK*")

    def lion(self):
        return print("roar")

    def __call__(self):
        setattr(clown, 'isFunny', True)
        setattr(lion, 'isFunny', False)

My config file:

circus = {
    'funny_thing': Circus.clown,
    'unfunny_thing': Circus.lion
}

And the actual script:

for item in circus.items():
    if item[1].isFunny == True:
        item()

I've lost track of everything I've tried, but it's included separating this into two classes and creating an isFunny() method in each (returning true or false), assigning things to the class __dict__, placing setattr() in different places, using __init__, @staticmethod and @classmethod .

What I expect is a simple *HONK* , but most everything spits out an AttributeError: 'function' object has no attribute 'isFunny' .

What am I doing wrong?


For reference, a handful of the links I've tried:

__call__ is invoked when you call an instance. Given c = Circus() , c() is the same as c.__call__() . As a result, you are trying to check the attribute before it gets defined. Further, inside the __call__ method, neither clown nor lion have been defined. They are both class attributes, and need to be used as such (ie, either Circus.clown or self.clown ). If you want to tag the methods, just do so directly in the class statement.

class Circus:
    def clown(self):
        print("*HONK*")

    def lion(self):
        print("roar")

    clown.isFunny = True
    lion.isFunny = False

circus = {
    'funny_thing': Circus.clown,
    'unfunny_thing': Circus.lion
}


for item in circus.items():
    if item[1].isFunny:
        item[1]()

However, note that item[1]() is still wrong, because the unbound method still expects an instance of Circus as its first argument. Some suggested fixes, depending on what you are actually trying to accomplish:

  1. Make the methods class methods or static methods, so that no additional arguments are needed.

  2. Store bound methods in the dict:

     c = Circus() circus = { 'funny_thing': c.clown, 'unfunny_thing': c.lion }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM