简体   繁体   English

在python的主类中使用subclass属性

[英]using subclass attribute in the main class in python

I'm trying to set the self.role under credential class to use the self.role under AXL class. 我正在尝试将凭证类下的self.role设置为使用AXL类下的self.role。 the idea is to have different classes based on the role the api needs to be. 想法是根据api的角色来设置不同的类。 if axl class is only reading data then the role would be r. 如果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())

the result would be 结果将是

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

Instead of rx, I need to see r 我需要看到r而不是rx

Here is a link to the sandbox 这是沙盒的链接

Answer by @chepner is definitely correct solution. @chepner的回答绝对是正确的解决方案。 I'll leave this here as a homage to over complicating a simple problem. 我将其保留在这里,是为了过分复杂的简单问题。

You could make username_file a @property on Credential so it's evaluated on access not on instance creation. 您可以在Credential上将username_file@property ,以便在访问@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

If it's an instance of AXL roll will be 'r' and 'rx' if instance of Credential . 如果是AXL实例,则roll为'r',如果为Credential实例,则为'rx'。

You can also cache the result of the first property access if you want to streamline: 如果要简化,还可以缓存第一个属性访问的结果:

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

role should be an parameter of Credential.__init__ , not hard-coded, although it could have a default value for the base class. role应该是Credential.__init__的参数,而不是硬编码的,尽管它可以具有基类的默认值。 Subclasses would pass the required role directly to super().__init__ . 子类会将所需的角色直接传递给super().__init__ (If there is something that must have a role of 'rx' , that should be a subclass of Credential as well, not Credential itself.) (如果某些东西必须具有'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

To play nicer with super , you might consider using keyword-only arguments for __init__ : 为了更好地使用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)

Ok, the problem here is basically the data type of username_file ; 好的,这里的问题基本上是username_file的数据类型; its a string created in the constructor and does not update when it's components do. 它是在构造函数中创建的字符串,并且在组件运行时不会更新。 There are a few ways to go around this, using properties is a pretty good and clean way to go about it: 有几种方法可以解决此问题,使用属性是解决问题的一种非常不错的方法:

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())

EDIT: 编辑:

Just a short explanation, you can turn to a property pretty much any variable, the reason for selecting role is resource management. 只是一个简短的解释,您几乎可以将任何变量都转换为属性,选择角色的原因是资源管理。 Essentially, it takes fewer resources to update username_file in the setter every time role changes (once in the program) than add strings (slow operation) every time you call the getter. 从本质上讲,每次角色更改(程序中一次)时,在setter中更新username_file所需的资源少于每次调用getter时添加字符串(慢操作)所需的资源。 Of course, considering the size of the program resource management should not be a deal breaker, but mentioning to explain the logic of the answer. 当然,考虑程序资源管理的规模不应该成为交易的障碍,而应提及解释答案的逻辑。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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