我有2个具有某些功能的类:
class A:
def __init__(self, one=1, two=2):
self.one = one
self.two = two
def do_smt(self):
...
class B:
def __init__(self, value="test"):
self.value = value
def do_smt(self):
...
我有一个第三类,必须使用这两个类。
class C:
def __init__(self, one=1, two=2, value="test"):
self.A = A(one, two)
self.B = B(value)
def do_smt(self):
...
现在我这样做:new_class = C()
但是如果class A or B
的默认值更改了,那我还需要在class C
中更改它。是否可以通过一种方式知道自己的默认参数来写class C
?它不需要处理任何参数,也不需要处理其他类期望的参数。
答案 0 :(得分:1)
您可以使用inspect.signature
获取类__init__
的每个“基础”类的C
方法的参数,并让C.__init__
接受可变关键字参数,因此它可以遍历“基”类,并传递给每个__init__
方法,只需要它以及给定关键字参数具有什么。使用itertools.islice
忽略第一个参数,该参数始终为self
:
import inspect
from itertools import islice
class C:
bases = A, B
params = {}
for cls in bases:
params[cls] = inspect.signature(cls.__init__).parameters
def __init__(self, **kwargs):
for cls in self.bases:
setattr(self, cls.__name__, cls(**{key: kwargs[key] for key in
islice(self.params[cls], 1, None) if key in kwargs}))
这样:
c = C(one=3,value='hi')
print(c.A.one)
print(c.A.two)
print(c.B.value)
输出:
3
2
hi
答案 1 :(得分:0)
您可以使用一些哨兵值(此处为None
),并且仅在提供有意义的参数时才传递参数:
class C:
def __init__(self, one=None, two=None, value=None):
if one is two is None:
self.A = A()
else:
self.A = A(one, two)
if value is None:
self.B = B()
else:
self.B = B(value)
这样,A
和B
的默认值可以照顾自己。
答案 2 :(得分:0)
在调用类A和B之前,为变量定义初始化值
尝试在C类init调用之前添加这些内容:
self.initA_one = A.one
self.initA_two = A.two
self.initB_value = B.value
并继续
self.A = A (.,.)
self.B = B (.)
编辑:
这就是我的意思。
class C():
def __init__(self, one=-1, two=-2, value="detest"):
self.initA_one = A().one
self.initA_two = A().two
self.initB = B().value
self.A = A(one, two)
self.B = B(value)
def do_smt(self):
print()
new_class = C()
print(f'default A.one is {new_class.initA_one}, new value A.one is {new_class.A.one}.')
print(f'default A.two is {new_class.initA_two}, new value A.two is {new_class.A.two}.')
print(f'default B.value is {new_class.initB}, new B.value is {new_class.B.value}')
给予
default A.one is 1, new value A.one is -1.
default A.two is 2, new value A.two is -2.
default B.value is test, new B.value is detest
答案 3 :(得分:0)
一种解决方案是将默认值分解为常量:
DEFAULT_ONE = 1
DEFAULT_TWO = 2
class A:
def __init__(self, one=DEFAULT_ONE, two=DEFAULT_TWO):
pass
也使用class C
中的常量。
答案 4 :(得分:0)
我不确定这是否完全符合您的要求,但是基本上,您可以让C决定给A,B的内容,然后让A,B使用A和B中的**kwds
方法参数来决定使用什么。 B。
与示例类C2的区别之一是,如果C具有不同的默认值,它将覆盖A,B。
在C3下,还有另一种选择,您可以使用保护值(不使用None来使它成为默认值)仅传递给C3的参数。
class A:
def __init__(self, one=1, two=2, **kwds):
self.one = one
self.two = two
def do_smt(self):
pass
class B:
def __init__(self, value="test", **kwds):
self.value = value
class C:
def __init__(self, one=1, two=2, value="test"):
self.A = A(one, two)
self.B = B(value)
class C2:
""" your default values override those of A, B"""
def __init__(self, one=1, two=2, value="test"):
locals_ = locals()
locals_.pop("self")
self.A = A(**locals_)
self.B = B(**locals_)
undefined = NotImplemented
class C3:
""" your default values dont affect A and Bs"""
def __init__(self, one=undefined, two=undefined, value="test"):
locals_ = {k:v for k,v in locals().items() if k != "self" and v is not undefined}
self.A = A(**locals_)
self.B = B(**locals_)
#can still use it locally
self.one = one if one is not undefined else 11
self.two = two if two is not undefined else 22
c= C()
print("c.A.one:", c.A.one)
print("c.B.value:", c.B.value)
c2= C2()
print("c2.A.one:", c2.A.one)
print("c2.B.value:", c2.B.value)
c3= C3()
print("c3.A.one:", c3.A.one)
print("c3.one:", c3.one)
print("c3.B.value:", c3.B.value)
c.A.one: 1
c.B.value: test
c2.A.one: 1
c2.B.value: test
c3.A.one: 1
c3.one: 11
c3.B.value: test
您甚至可以使用C的变体,使其本身使用**kwds
并将它们传递给A,B,以防他们在其中找到价值。
class C4:
""" your default values dont affect A and Bs
and you can pass in anything.
Neither two or value are known to C and that's OK"""
def __init__(self, one=undefined, **kwds):
locals_ = locals()
locals_ = {k:v for k,v in locals().items() if k not in ("self","kwds") and v is not undefined}
locals_.update(**kwds)
self.A = A(**locals_)
self.B = B(**locals_)
#can still use it locally
self.one = one if one is not undefined else 11
c4= C4(value="somevalue")
print("c4.A.one:", c4.A.one)
print("c4.A.two:", c4.A.two)
print("c4.one:", c4.one)
print("c4.B.value:", c4.B.value)
c4.A.one: 1
c4.A.two: 2
c4.one: 11
c4.B.value: somevalue