Python 如何仅获取父类对象的属性

Python 如何仅获取父类对象的属性,python,python-3.x,class,oop,inheritance,Python,Python 3.x,Class,Oop,Inheritance,我有两门课: class Parent(object): def __init__(self, id, name): self.id = id self.name = name self.__parent_vars = ['id', 'name'] # make a copy def print_values(self): res = {} for el in self.__parent_vars

我有两门课:

class Parent(object):
    def __init__(self, id, name):
        self.id = id
        self.name = name
        self.__parent_vars = ['id', 'name']  # make a copy

    def print_values(self):
        res = {}
        for el in self.__parent_vars:
            res[el] = vars(self)[el]
        return res


class Child(Parent):
    def __init__(self, id, name, last_name, age):
        Parent.__init__(self, id, name)
        self.last_name = last_name
        self.age = age
我想做的是——从
Parent
类的
Child
参数中获取。我使用附加变量来实现它,并且它可以工作,但是我需要更优雅的解决方案,而不需要附加变量。我在泡菜课上需要它。如果我创建额外的变量,它会在一个大项目中破坏我的模式

我试图找到这样的东西:

c = Child(12,"Foo","whatever",34)
vars(c.super())
预期产出:

{'id': 12, 'name': 'Foo'}


我发现了这个问题:但它和我的有很大的不同,所以我不能使用这个解决方案。

恐怕你不能轻易地解决这个问题。在Python中,类只携带方法和静态属性。不 静态属性通常存储在对象的
\uuu dict\uu
属性中。这意味着,除特殊情况外,您无法轻松知道在父类方法、子类方法甚至任何方法之外分配了哪些属性

我只能想象一个meta_类,它将使用
\uuuu init\uuu
方法来存储调用期间更改的属性:

import collections
import functools
import inspect

class Meta_attr(type):
    init_func = {}
    attrs = collections.defaultdict(set)

    def __new__(cls, name, bases, namespace, **kwds):
        c = type.__new__(cls, name, bases, namespace, **kwds)
        cls.init_func[c] = c.__init__
        @functools.wraps(c.__init__)
        def init(self, *args, **kwargs):
            before = set(self.__dict__.keys())
            cls.init_func[c](self, *args, **kwargs)
            after = set(self.__dict__.keys())
            cls.attrs[c].update(after.difference(before))
        init.__signature__ = inspect.signature(c.__init__)
        c.__init__ = init
        return c

class Parent(object, metaclass=Meta_attr):
    def __init__(self, id, name):
        self.id = id
        self.name = name

    def print_values(self):
        res = {}
        for el in Meta_attr.attrs[Parent]:
            res[el] = vars(self)[el]
        return res


class Child(Parent):
    def __init__(self, id, name, last_name, age):
        Parent.__init__(self, id, name)
        self.last_name = last_name
        self.age = age
它给出:

>>> c = Child(1,"a","b", 20)
>>> c.print_values()
{'id': 1, 'name': 'a'}

小心:如果在
\uuuuu init\uuuuuu
方法之外设置了一个属性,那么它将不会被这个元类注册…

我又找到了一个解决方案。它看起来更简单,所以我用了它。它基于使用 此外,它在我的项目中更有用,因为我已经使用了棉花糖模式。 想法:我创建了两个类和两个不同的模式。并且可以仅使用父模式序列化更大的类(子):

代码 定义两个类: 定义2个模式: 使用它仅获取子对象的父属性:
它们是通过分配给
self
而创建的,self已经是
子项
。属性不跟踪创建它们的函数。至少在某种程度上,您需要继续明确定义哪些属性属于父级。(
self.\uuu parent\u vars=list(self.\uu dict\uuuu)
可能是一个选项。)@Ry-感谢您的回复!这是否意味着这是不可能的?一些
super
提示还是其他什么?或者一些关于创建一些附加方法而不是字段的提示?
vars(c)
prints:
{'id':12,'name':'Foo','u Parent\u Parent\u vars':['id','name'],'last\u name':'whatever','age':34}/code>而不是
c.print\u values()
{id':12,'name':'Foo}
也许你应该在Child中创建新的
print_值
,它使用
super()。print_values()
执行parent
print_值
,然后将子值添加到parent值。@MatteoPeluso是的,当然:)这就是我问这个问题的原因)谢谢你的回答!正如我所见,它解决了这个问题,但看起来使用其他字段
\uu parent\u vars
很容易:D@Mikhail_Sam:元类是一个非常强大的工具,它允许深入内部Python机制。它经常在大型框架中用于为用户定义的类提供一个统一的API,但我不确定它是否值得在这里使用。只有你能说…我又找到了一个解决办法。请看一看。
class Parent(object):
    def __init__(self):
        self.id = 'ID'
        self.name = 'some_name'

class Child(Parent):
    def __init__(self):
        Parent.__init__(self)
        self.last_name = 'last_name'
        self.age = 15

from marshmallow import Schema, fields, EXCLUDE
class ParentSchema(Schema):
    ba = Parent()
    id = fields.Str(missing=ba.id)
    name = fields.Str(missing=ba.name)

class ChildSchema(Schema):
    ba = Child()
    id = fields.Str(missing=ba.id)
    name = fields.Str(missing=ba.name)

    last_name = fields.Str(missing=ba.last_name)
    age = fields.Int(missing=ba.age)
user_data = {'id':'IDIDID', 'name':'add_name', 'last_name':'FAMILIYA'}
res = ParentSchema().load(user_data, unknown=EXCLUDE)

# output:
res
{'name': 'add_name', 'id': 'IDIDID'}