1 回答

TA貢獻1872條經驗 獲得超4個贊
子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"
添加回答
舉報