我第一次在python项目中使用OOP工作。我有3个班级:PRA,GDB和XLS。
PRA = Main Class
GDB = Responsible for control databases
XLS = Responsible for control xls(x)
UserInput = Responsible for validate user input
我是怎么做的:
PRA:
class PRA(GDB, XLS, UserInput):
__init__():
self.gdb_file, self.xls_file = self.ask_questions() # <--- ask_questions is inside the UserInput class.
self.do_something()
XLS:
class XLS:
do_something():
print(self.xls_file)
__init__(self, xls_file):
self.xls_file = xls_file
GDB:
class GDB:
__init__(self, gdb_file):
self.gdb_file = gdb_file
我想知道在PRA中初始化gdb_file和xls_file是不好的做法。 init ,如果没有,我怎样才能运行self.xls_file和self.xls_gdb的初始化只在PRA?
答案 0 :(得分:0)
这不是一个真正的答案,而是更多的代码重用示例。不过,我不确定这是不是超级Pythonic。无论如何,看看这个例子:
import inspect
class A:
def __init__(self):
self.a = 1
class B:
def __init__(self):
self.b = 2
class C(A, B):
def __init__(self):
for super_class in inspect.getmro(type(self))[1:]:
super_class.__init__(self)
c = C()
print(c.a, c.b)
答案 1 :(得分:0)
有点旧,但你可能想对你的班级名单三思而后行......他们真的太可怕了。
现在wrt /你的问题......从技术上讲,处理父类正确初始化的方法是从子类中调用它的初始化,即:
class Parent(object):
def __init__(self, name):
self.name = name
class Child(Parent):
def __init__(self, name, age):
super(Child, self).__init__(name)
self.age = age
您还可以明确命名父类,即:
class Child(Parent):
def __init__(self, name, age):
Parent.__init__(self, name)
self.age = age
但它有一些缺点,比如在调用中对父类进行编码(如果你改变父类,你有两个或更多的地方可以编辑),更重要的是,没有正确解决“钻石“多重遗传问题(即B&C的D儿童,A的B儿童,A的C儿童)。
实际上,不使用super()
的唯一原因是父类构造函数不兼容,但这是一种巨大的设计气味 - 如果你有两个或多个不兼容的父类,那么你肯定不会以正确的方式使用继承。在您的示例中实际情况就是这样:您的“主”类“不是”“数据库控制器”,而是使用数据库控制器,因此您希望使用合成而不是继承
class ServiceA(object):
# code here
class ServiceB(object):
# code here
class Main(object):
def __init__(self, arg1, arg2, arg3):
self.arg1 = arg1
self.service_a = ServiceA(arg2)
self.service_b = ServiceB(arg3)
def run(self):
something = self.service_a.ask(question)
self.service_b.do_something_with(something)
此外,您可能希望避免构造函数中的用户交互和代价高昂的资源获取...更好地使用第一种情况的入口点方法(如app = MyApp(params)
; app.run()`)和延迟初始化第二种情况(等到你需要资源来获取它,使用私有属性作为缓存一个公共属性,在第一次访问时负责获取)。
[编辑]
有人建议基于内省的肮脏黑客,即:
import inspect
class A:
def __init__(self):
self.a = 1
class B:
def __init__(self):
self.b = 2
class C(A, B):
def __init__(self):
for super_class in inspect.getmro(type(self))[1:]:
super_class.__init__(self)
c = C()
print(c.a, c.b)
绝对不是要做的事情。
如果您的所有父类都具有兼容的构造函数并正确使用super
调用,那么您只需使用super
代替:
class A(object):
def __init__(self):
super(A, self).__init__()
self.a = "a"
class B(object):
def __init__(self):
super(B, self).__init__()
self.b = "b"
class C(A, B):
def __init__(self):
super(C, self).__init__()
self.c = "c"
c = C()
print c.a, c.b, c.c
这也通过以正确的顺序调用父类来处理“钻石继承”问题:
class D(C, A):
def __init__(self):
super(D, self).__init__()
self.d = "d"
d = D()
print "d : ", d.a, d.b, d.c, d.d
请注意,除非只有一个父类是“正确的”类(带有状态),而所有其他类都是mixin类(只添加功能的无状态类),所以多重继承通常不是设计气味(同样作为一个维持地狱)。由于Python不使用静态类型,因此继承主要用于实现继承,并且在很多情况下,组合/委托(或者只是在OP情况下的简单组合)是比实现继承更好的解决方案。