gpt4 book ai didi

python - 如何在Python中从现有的父类(super class)类型对象实例化子类类型变量

转载 作者:行者123 更新时间:2023-12-02 19:20:34 25 4
gpt4 key购买 nike

我有一种情况,我用多个属性扩展一个类:

class SuperClass:
def __init__(self, tediously, many, attributes):
# assign the attributes like "self.attr = attr"

class SubClass:
def __init__(self, id, **kwargs):
self.id = id
super().__init__(**kwargs)

然后我想创建实例,但我明白这会导致子类只能像这样实例化的情况:

super_instance = SuperClass(tediously, many, attributes)

sub_instance = SubClass(id, tediously=super_instance.tediously, many=super_instance.many, attributes=super_instance.attributes)

我的问题是,是否可以通过复制父类(super class)实例的属性来实例化子类,而无需编写一段香肠代码来手动执行此操作(无论是在构造函数调用中,还是在构造函数函数体内) )...类似:

utopic_sub_instance = SubClass(id, **super_instance)

最佳答案

也许您想要一些关于如何不编写这么多代码的具体想法?所以一种方法是这样的:

class A:
def __init___(self, a, b, c):
self.a = a
self.b = b
self.c = c


class B:
def __init__(self, x, a, b, c):
self.x = x
super().__init__(a, b, c)


a = A(1, 2, 3)
b = B('x', 1, 2, 3)


# so your problem is that you want to avoid passing 1,2,3 manually, right?
# So as a comment suggests, you should use alternative constructors here.
# Alternative constructors are good because people not very familiar with
# Python could also understand them.
# Alternatively, you could use this syntax, but it is a little dangerous and prone to producing
# bugs in the future that are hard to spot


class BDangerous:
def __init__(self, x, a, b, c):
self.x = x
kwargs = dict(locals())
kwargs.pop('x')
kwargs.pop('self')

# This is dangerous because if in the future someone adds a variable in this
# scope, you need to remember to pop that also
# Also, if in the future, the super constructor acquires the same parameter that
# someone else adds as a variable here... maybe you will end up passing an argument
# unwillingly. That might cause a bug
# kwargs.pop(...pop all variable names you don't want to pass)
super().__init__(**kwargs)


class BSafe:
def __init__(self, x, a, b, c):
self.x = x
bad_kwargs = dict(locals())

# This is safer: you are explicit about which arguments you're passing
good_kwargs = {}
for name in 'a,b,c'.split(','):
good_kwargs[name] = bad_kwargs[name]

# but really, this solution is not that much better compared to simply passing all
# parameters explicitly
super().__init__(**good_kwargs)

或者,让我们来得更疯狂一点。我们将使用内省(introspection)来动态构建字典以作为参数传递。我的示例中没有包含仅关键字参数、默认值、*args 或 **kwargs

class A:
def __init__(self, a,b,c):
self.a = a
self.b = b
self.c = c


class B(A):
def __init__(self, x,y,z, super_instance):
import inspect
spec = inspect.getfullargspec(A.__init__)

positional_args = []
super_vars = vars(super_instance)

for arg_name in spec.args[1:]: # to exclude 'self'
positional_args.append(super_vars[arg_name])

# ...but of course, you must have the guarantee that constructor
# arguments will be set as instance attributes with the same names
super().__init__(*positional_args)

关于python - 如何在Python中从现有的父类(super class)类型对象实例化子类类型变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63117963/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com