Python-重写父类属性而不实例化
如何在不使用任何一个类的对象实例的情况下覆盖子类中的父类属性?来自Java/C++及其严格的结构设计的世界,我发现自己受到Python处理方式的挑战。我想保持相对静止 示例:Python-重写父类属性而不实例化,python,oop,inheritance,overriding,subclass,Python,Oop,Inheritance,Overriding,Subclass,如何在不使用任何一个类的对象实例的情况下覆盖子类中的父类属性?来自Java/C++及其严格的结构设计的世界,我发现自己受到Python处理方式的挑战。我想保持相对静止 示例: from urllib.parse import urljoin class base: host = "/host/" path = "Override this in child classes" url = urljoin(host, path) c
from urllib.parse import urljoin
class base:
host = "/host/"
path = "Override this in child classes"
url = urljoin(host, path)
class config(base):
path = "config"
@classmethod
def print_url(cls):
print(cls.url) # Currently prints "/host/Override this in child classes"
# Would like to print "/host/config" instead
class log(base):
path = "log"
@classmethod
def print_url(cls):
print(cls.url) # Currently prints "/host/Override this in child classes"
# Would like to print "/host/log" instead
所需用途:
>>> config.print_url()
/host/config
>>> log.print_url()
/host/log
我希望config.path
和log.path
属性覆盖base.path
。这样我就可以在base
类中一次性使用url=urljoin(host,path)
(避免在每个派生类中复制/粘贴相同的属性/计算)
我不知道如何在不构建对象的情况下实现这一点(我希望避免构建对象)。有人有什么建议吗?提前谢谢 子
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"
请注意,您现在正在动态地引用实际类的主机
和路径
。您还只需要在base
中使用一个print\u url
方法,而不是在每个类中使用不同的方法
另一个选项是为base
及其所有子级提供一个元类,并将url
作为属性
:
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类也是对象。您可以在类(元类)的类中定义属性
,它的行为与任何属性
对实例的行为相同。这一次,实例本身就是一个类
第三个选项是确保在每个子项中静态但正确地定义url
。该方法允许您非常方便地直接从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"
Python类也是对象。“你可以这样对待他们。”Mad_物理学家非常感谢你给出的详细答案,这正是我想要的!!我不知道元类或init_子类的存在,我现在要将它们添加到我的工具带中!