在python的主类中使用subclass属性

时间:2019-03-22 11:39:41

标签: python oop

我正在尝试将凭证类下的self.role设置为使用AXL类下的self.role。想法是根据api的角色来设置不同的类。如果axl类仅读取数据,则角色将为r。

PATH = 'home_drive_'
PLATFORM = 'Linux_'
ITEM = '_PC'

class Credential:

    def __init__(self, path, platform):
        self.role = 'rx'
        self.username_file = path + platform + ('The role should be the same as AXL role: ' + self.role)

class AXL(Credential):

    def __init__(self, path, platform, item):
        super().__init__(path, platform)
        self.role = 'r'
        self.item = item

    def final(self):
        return self.username_file + self.item

reg1 = AXL(PATH, PLATFORM, ITEM)

print('AXL role:', reg1.role)
print(reg1.username_file)
print(reg1.final())

结果将是

AXL role: r 
home_drive_Linux_The role should be the same as AXL role: rx 
home_drive_Linux_The role should be the same as AXL role: rx_PC

代替rx,我需要看r

这是沙箱中的link

3 个答案:

答案 0 :(得分:2)

Answer by @chepner绝对是正确的解决方案。我将其保留在这里,是为了过分复杂的简单问题。

您可以在username_file上将Credential设为@property,以便根据访问权限(而不是实例创建)对其进行评估。

class Credential:
    def __init__(self, path, platform):
        self.role = 'rx'
        self.path = path
        self.platform = platform

    @property
    def username_file(self):
        return self.path + self.platform + self.role

如果是AXL实例,则滚动将为'r',如果是Credential实例则为'rx'。

如果要简化,还可以缓存第一个属性访问的结果:

class Credential:
    def __init__(self, path, platform):
        self.role = 'rx'
        self.path = path
        self.platform = platform
        self._username_file = None

    @property
    def username_file(self):
        if not self._usernme_file:
            self._username_file = self.path + self.platform + self.role
        return self._username_file

答案 1 :(得分:2)

role应该是Credential.__init__的参数,而不是硬编码的,尽管它可以具有基类的默认值。子类会将所需角色直接传递给super().__init__。 (如果某些东西必须具有'rx'的角色,那么它们也应该是Credential的子类,而不是Credential本身。)

class Credential:

    def __init__(self, path, platform, role='rx'):
        self.role = role
        self.username_file = path + platform + ('The role should be the same as AXL role: ' + role)


# class SomethingNeedingRoleRX(Credential):
#      def __init__(self, path, platform):
#          super().__init__(path, platform, 'rx')


class AXL(Credential):

    def __init__(self, path, platform, item):
        super().__init__(path, platform, 'r')
        self.item = item

    def final(self):
        return self.username_file + self.item

要更好地使用super,您可以考虑为__init__使用仅关键字的参数:

class Credential:
    def __init__(self, *, path, platform, role='rx', **kwargs):
        super().__init__(**kwargs)
        self.role = role
        self.username_file = path + platform + role


class AXL(Credential):
    def __init__(self, *, item, **kwargs):
        super().__init__(role='r', **kwargs)
        self.item = item

    def final(self):
        return self.username_file + self.item


reg1 = AXL(path=PATH, platform=PLATFORM, item=ITEM)

答案 2 :(得分:1)

好吧,这里的问题基本上是username_file的数据类型;它是在构造函数中创建的字符串,并且在组件运行时不会更新。有几种方法可以解决此问题,使用属性是一种很好而干净的方法:

PATH = 'home_drive_'
PLATFORM = 'Linux_'
ITEM = '_PC'


class Credential:
    def __init__(self, path, platform):
        self.path = path
        self.platform = platform
        self.role = 'rx'
        self.username_file = self.path + self.platform + ('The role should be the same as AXL role: ' + self.role)

    @property
    def role(self):
        return self._role

    @role.setter
    def role(self, new_role):
        self._role = new_role
        self.username_file = self.path + self.platform + ('The role should be the same as AXL role: ' + self.role)


class AXL(Credential):
    def __init__(self, path, platform, item):
        super().__init__(path, platform)
        self.role = 'r'
        self.item = item

    def final(self):
        return self.username_file + self.item


reg1 = AXL(PATH, PLATFORM, ITEM)

print('AXL role:', reg1.role)
print(reg1.username_file)
print(reg1.final())

编辑:

仅作简短说明,您几乎可以将任何变量都转换为属性,选择角色的原因是资源管理。 从本质上讲,每次角色更改(在程序中一次)时,在setter中更新username_file所花费的资源要少于每次调用getter时添加字符串(慢操作)所花费的资源。当然,考虑到程序资源管理的规模,不应该成为交易的障碍,而应提及解释答案的逻辑。