1 回答
TA贡献1872条经验 获得超3个赞
子path属性会覆盖base.path。您不覆盖的是url属性。当运行 的主体base来创建类对象时,就会计算一次。
未来你有几个选择。无论哪种方式,您都需要url动态地进行计算,或者每次访问它时,或者每个子类至少一次。
最简单的方法是制作url成classmethod:
class base:
host = "/host/"
path = "Override this in child classes"
@classmethod
def url(cls):
return urljoin(cls.host, cls.path)
@classmethod
def print_url(cls):
print(cls.url())
class config(base):
path = "config"
class log(base):
path = "log"
请注意,您现在指的是实际的类host并且path是动态的。您还只需要一种print_url方法,base而不是每个类中使用不同的方法。
base另一种选择是为 及其所有子级提供一个元类,url其形式为property:
class url_meta(type):
@property
def url(cls):
return urljoin(cls.host, cls.path)
class base(metaclass=url_meta):
host = "/host/"
path = "Override this in child classes"
@classmethod
def print_url(cls):
print(cls.url)
class config(base):
path = "config"
class log(base):
path = "log"
这是可行的,因为 python 类也是对象。property您可以在类的类(元类)中定义 a ,它的行为与任何property对实例的行为一样。这次实例本身就是一个类。
第三种选择是确保url在每个子项中静态但正确地定义它。该__init_subclass__方法允许您直接从以下位置非常方便地执行此操作base:
class base:
host = "/host/"
path = "Override this in child classes"
url = urljoin(host, path)
@classmethod
def __init_subclass__(cls):
cls.url = urljoin(cls.host, cls.path)
@classmethod
def print_url(cls):
print(cls.url)
class config(base):
path = "config"
class log(base):
path = "log"
您也可以使用元类完成同样的事情:
class url_meta2(type):
def __init__(cls, *args, **kwargs):
cls.url = urljoin(cls.host, cls.path)
class base(metaclass=url_meta2):
host = "/host/"
path = "Override this in child classes"
@classmethod
def print_url(cls):
print(cls.url)
class config(base):
path = "config"
class log(base):
path = "log"
添加回答
举报