在类继承和super()中挣扎。

时间:2018-07-02 20:54:33

标签: python inheritance

Python的新手,试图创建一个可以创建任意数量的军队的游戏,但每支军队都会预先渲染士兵的姓名。

我认为我需要使用super init来真正减少重复的代码,但是我一生都无法弄清楚如何使其工作。据我了解,我的班级DELIMITER $$ CREATE DEFINER=`mjrinker`@`localhost` PROCEDURE `rand_id`(IN `min` BIGINT, IN `max` BIGINT, IN `tablename` VARCHAR(128) CHARSET utf8, OUT `uid` BIGINT) BEGIN SET @count_id = 1; SET uid = 0; SET @s = CONCAT('SELECT COUNT(`id`) INTO @count_id FROM `', tablename, '` WHERE `id` = ?'); PREPARE stmt from @s; WHILE @count_id > 0 DO SET @uid = FLOOR(rand() * max + min); EXECUTE stmt USING @uid; END WHILE; DEALLOCATE PREPARE stmt; SET uid = @uid; END$$ DELIMITER ; 应该是父级班级,ArmyRedArmy是子类。我只是在努力了解Scout应该放在哪里?

super().__init__()

2 个答案:

答案 0 :(得分:5)

放置super().__init__(如果有的话)的位置取决于类层次结构的具体情况。

最常见的是,如果它放在您的位置很重要,那么您希望它在子类的__init__方法的开始。这样可以确保所有基类变量都已设置,其所有不变量都得到满足,并且其所有方法都可以由其余子类__init__代码调用。

这很重要,因为您要在基类和子类中设置相同的属性。您显然希望将子类版本作为需要的版本,因此它必须在默认分配之后,而不是在以下之前:

class RedArmy(Army):
    def __init__(self):
        super().__init__()
        self.color = "Red"
        self.scoutname = "Yankee"
        self.demomanname = "Irish"
        self.medicname = "Dutch"

但是,值得考虑的是,您是否真的希望基类首先将这些变量设置为None

我假设在您的真实代码中,BlueArmy不仅会去pass,而且会做与RedArmy相同的事情,将所有这些值替换为一些弦。

此外,您的其余代码可能会假定那里有有效的字符串,而不是None。像TypeError: '<' not supported between instances of 'NoneType' and 'str'这样的异常比AttributeError: 'GreenArmy' object has no attribute 'scoutname'更难调试,而不是更容易,所以为什么不只保留默认值呢?然后,您可以完全消除Army.__init__,而不必担心首先要在子类初始化程序中调用super

或者,或者,您可以让Army.__init__接受用于分配值的参数,并使子类调用super().__init__("Red", "Yankee", "Irish", "Dutch")。然后,Army()将引发一个TypeError而不是创建一个无效的Army实例。或者,您可以创建一个名为@abstractmethod的{​​{1}}并self._setup()调用并期望每个子类提供,因此Army.__init__会引发关于实例化一个更有意义的Army()的信息。抽象类。这些改进使调试TypeError子类变得更容易-如果您只有两个子类,它们可能只是浪费时间,但是如果您有很多子类,那么这些子类将由不同的人开发还是很长一段时间,这可能是值得的。

答案 1 :(得分:-1)

如果要让类利用superinit的话,将值作为参数传递是最有意义的:

class Army:    
    def __init__(self, color=None, scoutname=None, demomanname=None,
                 medicname=None):
        self.color = color
        self.scoutname = scoutname
        self.demomanname = demomanname
        self.medicname = medicname

    def train_scout(self, weapon):
        return Scout(self.color, self.scoutname, weapon)


class RedArmy(Army):
    def __init__(self, color="Red", scoutname="Yankee", demomanname="Irish",
                 medicname="Dutch"):
        super().__init__(color, scoutname, demomanname, medicname)


class Scout:
    specialization = "fast captures"

    def __init__(self, color, scoutname, weapon):
        self.color = color
        self.scoutname = scoutname
        self.weapon = weapon

    def introduce(self):
        return (
            f'Hi I\'m {self.scoutname}, I do {self.specialization} and I wield '
            f'a {self.weapon}')


my_army = RedArmy()    
soldier_1 = my_army.train_scout("baseball bat")
print(soldier_1.introduce())