我正在使用元类设置类属性fields
:
class MyMeta(type):
def __new__(mcs, name, bases, clsdict):
clsdict['fields'] = {k: v
for k, v in clsdict.items()
if <my_condition>}
return super(MyMeta, mcs).__new__(mcs, name, bases, clsdict)
class MyBaseClass(metaclass=MyMeta):
fields = {}
以下实例化会产生预期结果:
class SubClass(MyBaseClass):
param1 = 1 # meets <my_condition>
>>> SubClass.fields
{param1: 1}
但如果我现在继承SubClass
,fields
为空:
class SubSubClass(SubClass):
pass
>>> SubSubClass.fields
{}
如何更新继承层次结构中所有类的classdict,以便从基类更新fields
变量?
答案 0 :(得分:4)
你需要以某种方式保留超类的public Flowable<List<Book>> getItems(String query) {}
textChangeSubscriber
.debounce(300, TimeUnit.MILLISECONDS)
.observeOn(Schedulers.computation())
.switchMap(s -> getItems(s).toObservable())
.flatMapIterable(items -> items)
.map(Book::convert)
.toList()
.observeOn(AndroidSchedulers.mainThread())
.subscribe(books -> {
Log.i("test", "" + books.toString());
}, error -> {
Log.i("test", "" + error);
});
getItems(query).flatMapIterable(items -> items)
.map(Book::convert)
.toList()
.observeOn(AndroidSchedulers.mainThread())
.subscribeOn(Schedulers.io())
.subscribe(books -> {
Log.i("test", "" + "" + books.toString());
}, error -> {
Log.i("test", "" + error);
});
,例如通过迭代“基础”并使用他们的fields
作为起点:
fields
适用于class MyMeta(type):
def __new__(mcs, name, bases, clsdict):
if 'fields' not in clsdict:
clsdict['fields'] = {}
# Initialize "fields" from base classes
for base in bases:
try:
clsdict['fields'].update(base.fields)
except AttributeError:
pass
# Fill in new fields (I included a "trivial" condition here, just use yours instead.)
clsdict['fields'].update({k: v for k, v in clsdict.items() if k.startswith('param')})
return super(MyMeta, mcs).__new__(mcs, name, bases, clsdict)
和SubClass
:
SubSubClass
答案 1 :(得分:1)
我建议将fields
转换为属性描述符,该描述符从父类中获取_fields
的所有内容。这样,您还可以更轻松地自定义名称冲突等时发生的情况。
class MyMeta(type):
def __new__(mcs, name, bases, clsdict):
# change fields to _fields
clsdict['_fields'] = {k: v
for k, v in clsdict.items()
if <my_condition>}
return super(MyMeta, mcs).__new__(mcs, name, bases, clsdict)
@property
def fields(cls):
# reversed makes most recent key value override parent values
return {k:v
for c in reversed(cls.__mro__)
for k,v in getattr(c, '_fields', {}).items() }
用法:
class MyBaseClass(metaclass=MyMeta):
fields = {}
class SubClass(MyBaseClass):
param1 = 1
>>> SubClass.fields
{param1: 1}
class SubSubClass(SubClass):
pass
>>> SubSubClass.fields
{param1: 1} # success
现在,SomeChildClass.fields
的使用总是引用元类属性。 getattr
的第三个参数允许没有_fields
属性的类(例如object
)以静默方式失败。
使用描述符还具有防止子类意外覆盖fields
属性的优点:
>>> SubSubClass.fields = 1
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: can't set attribute
如果需要,您还可以创建一个setter,并在__init__
方法中使用它(即,返回使用fields
而不是_fields
),以便完整的其余部分该类是实现不可知的:
@fields.setter
def fields(cls, mapping):
try:
cls._fields.update(**mapping)
except AttributeError:
cls._fields = dict(**mapping)