简体   繁体   中英

defining method of class in if statement

I'm trying to create a class that will create objects with different methods based on an input. The point of this is to avoid using an if statement every time the method is called.

Below is the code I thought would work, but isn't working.

class Food:
    def __init__(self,food_type):
        self.food_type = food_type

        if food_type == 'cookie':
            print 'this is a cookie'
            def is_awesome(self):
                print "is awesome"
        else:
            print 'this is not a cookie'
            def is_awesome(self):
                print "not awesome"

Oreo = Food('cookie')
Oreo.is_awesome()

The code doesn't error on the def is_awesome(self) statement, but instead the Oreo.is_awesome() line raises the error:

"AttributeError: Food instance has no attribute is_awesome".

Is there a better way to make objects with different methods? and is there a reason why the method is_awesome isn't callable by 'Oreo.is_awesome'?

You have to define the method/function is_awesome(self) and then your if's inside it

class Food:
    def __init__(self,food_type):
        self.food_type = food_type

    def is_awesome(self):
         if self.food_type == 'cookie':
            print 'this is a cookie'
            print "is awesome"
         else:
            print 'this is not a cookie not awesome'
            print "not awesome"


Oreo = Food('cookie')
Oreo.is_awesome()

This works, tested!

Is there a better way to make objects with different methods?

Yes a way that works :) Polymorphism is a great candidate.

class Food:
  def is_awesome(self):
    print 'not awesome'

class Cookie(Food):
  def is_awesome(self):
    print 'is awesome'

and is there a reason why the method is_awesome isn't callable by 'Oreo.is_awesome'?

Yes, it's not bound to the instance (conventionally called self ) in any

I encountered a similar situation where I wanted different instances of a class to have one of the methods behave differently depending on the init values but still have the same method name, and didn't want to run if/else statements at every call to the method.

The simplest solution I found was to define a setter method that creates a pointer to the wanted behavior, and this setter method is only run once at initialization:

class Food:
    def __init__(self, food_type):
        self.food_type = food_type
        
        self.set_awesomeness()
    
    def is_awesome():
        return 'is awesome'

    def not_awesome():
        return 'not awesome'

    # Point to the wanted behavior
    def set_awesomeness(self):
        if self.food_type == 'cookie':
            self.awesomeness = Food.is_awesome()
        else:
            self.awesomeness = Food.not_awesome()

    def get_awesomeness(self):
        return self.awesomeness
    
cookie = Food('cookie')
cookie.get_awesomeness() # 'is awesome'

donut = Food('donut')
donut.get_awesomeness() # 'not awesome'

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