你好!
我需要每个子类都有自己的常量集。我发现了一种使用属性和重载setter方法的“正确”方法,但是:
我已经做了类似的事情:
class BaseClass:
def get_a(self):
raise NotImplementedError("Oooops")
def get_b(self):
raise NotImplementedError("Oooops")
class FirstClass(BaseClass):
def get_a(self):
return "a"
def get_b(self):
return "b"
class SecondClass(BaseClass)
def get_a(self):
return "A"
def get_b(self):
return "B"
class SomeClass:
def some_method(self, class_param):
return "{}-{}".format(class_param.get_a, class_param.get_b)
此方法也不能解决具有属性的方法的问题(最后一个除外),只是更紧凑。还有另一种方法,我觉得不好:
class BaseClass:
pass
class FirstClass(BaseClass):
A_CONST = "a"
B_CONST = "b"
class SecondClass(BaseClass)
A_CONST = "A"
B_CONST = "B"
class SomeClass:
def some_method(self, class_param):
return "{}-{}".format(class_param.A_CONST, class_param.B_CONST)
实际上,它解决了所有问题并且非常紧凑,但是它违反了继承规则(不是吗?)。
问题: 正确的方法是什么?
P.S。提供的代码是简化的示例,基类包含我在子类中使用的方法,请不要在此告诉我基类没有用。
答案 0 :(得分:2)
如果您希望基类指示它需要使用某些属性进行子类化,则可以将其设为abstract base class。
from abc import ABC, abstractmethod
class Base(ABC):
@property
@abstractmethod
def a(self):
raise NotImplementedError
@property
@abstractmethod
def b(self):
raise NotImplementedError
然后将不允许实例化Base
或其子类,除非它们重写了抽象方法。你可以做
class First(Base):
a = 1
b = 2
使用这些名称分配类属性,或
class Second(Base):
@Base.a.getter
def a(self):
return 3
@Base.b.getter
def b(self):
return 4
第二种方法的好处是,如果您尝试分配给属性,它将引发错误
Second().a = 5 # AttributeError
答案 1 :(得分:0)
您的第二个版本对我来说很好……每种语言对于“类”或“对象”的含义都有自己的约定,而这看起来相当“ Pythonic”
关于第一个版本的一个小评论是Python不在乎“重载”,您不需要包括:
class BaseClass:
def get_a(self):
raise NotImplementedError("Oooops")
完全可以,即:
class BaseClass:
pass
以及您的第一个版本。
这里的另一个可能有用的工具是property
装饰器,例如:
class FirstClass(BaseClass):
@property
def a(self):
return "a"
print(FirstClass().a)
将输出“ a
”
答案 2 :(得分:0)
如果key_name : [A_CONST, B_CONST]
类的child
保持不变,则super()
将解决您的所有问题(1., 2., 3.
)。
一种“ pythonic”解决方案将删除setter
类中的任何getter
和child
的重复项,并让BaseClass()
处理这些常见任务。 / p>
class BaseClass(object):
def __init__(self, a, b):
self._a_const = a
self._b_const = b
@property
def A_CONST(self):
return self._a_const
@property
def B_CONST(self):
return self._b_const
class FirstClass(BaseClass):
def __init__(self, _aconst, _bconst):
# Let Base class object hold my constants but FirstClass Constructor
# is setting the value. Look SecondClass
super(FirstClass, self).__init__(_aconst, _bconst)
class SecondClass(BaseClass):
def __init__(self, _aconst, _bconst):
# Magic happens here
super(SecondClass, self).__init__(_aconst, _bconst)
class SomeClass():
def some_method(self, class_param):
return "{}-{}".format(class_param.A_CONST, class_param.B_CONST)
firstobj = FirstClass("a", "b")
secondobj = SecondClass("A", "B")
print(SomeClass().some_method(firstobj))
print(SomeClass().some_method(secondobj))