使用元类继承类变量 [英] Using metaclasses to inherit class variables

查看:81
本文介绍了使用元类继承类变量的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想继承一些类变量的新副本。所以我设置了一个

元类并插入那里的类变量。


现在通过字典而不是
运行会很方便
显式设置每个变量。但是getattr()和setattr()都是
因为他们通过类层次结构来追逐变量。


所以,我直接用cls读了字典。 __dict __。has_key(var)。

阅读有效但当我直接设置对象的字典

时:


cls .__ dict __ [var] = val


我收到以下错误:


文件Table.py,第10行,__ init__

如果不是cls .__ dict __。has_key(var):cls .__ dict __ [var] = val

TypeError:调用元类库时出错

对象不支持项目分配


有一个简单的方法吗?或者我是否坚持列出

变量每行一个?


类SetClassVars(类型):

cvars = dict( name = None,desc = None,required = True,minlen = 1,

maxlen = 25,idDown = 999999999,idNext = 0)

def __init __(cls,name ,base,dict):

如果不是cls .__ dict __。has_key(''name''):cls.name = None

如果不是cls .__ dict __。has_key( ''desc''):cls.desc =无

如果不是cls .__ dict __。has_key(''required''):cls.required = True

如果没有cls .__ dict __。has_key(''minlen''):cls.minlen = 1

如果不是cls .__ dict __。has_key(''maxlen''):cls.maxlen = 25

如果不是cls .__ dict __。has_key(''idDown''):cls.idDown = 999999999

如果不是cls .__ dict __。has_key(''idNext''):cls.idNext = 0


#循环通过字典会更方便

#for var,val在SetClassVars.cvars.iteritems()中:


#getattr()和setattr()通过MRO运行

#这不是我想要的

#if not getattr(cls,var):setattr(cls,var ,val)

#if not cls .__ dict __。has_key(var):setattr(cls,var,val)


#设置字典直接生成一个错误

#if not cls .__ dict __。has_key(var):cls .__ dict __ [var] = val


thanks

t4

解决方案

te *********@gmail.com 写道:

我想继承一些类变量的新副本。所以我设置了一个
元类并在那里插入类变量。

现在通过字典运行而不是明确设置每个变量会很方便。但是getattr()和setattr()都没有了,因为它们通过类层次结构追逐变量。


getattr()确实如此,setattr()没有。

这有简单的方法吗?或者我是不是每行列出一个
变量?

类SetClassVars(类型):
cvars = dict(name = None,desc = None,required = True, minlen = 1,
maxlen = 25,idDown = 999999999,idNext = 0)
def __init __(cls,name,bases,dict):
如果不是cls .__ dict __。has_key('' name''):cls.name = None
如果不是cls .__ dict __。has_key(''desc''):cls.desc = None
如果不是cls .__ dict __。has_key(''required' '):cls.required = True
如果不是cls .__ dict __。has_key(''minlen''):cls.minlen = 1
如果不是cls .__ dict __。has_key(''maxlen'') :cls.maxlen = 25
如果不是cls .__ dict __。has_key(''idDown''):cls.idDown = 999999999
如果不是cls .__ dict __。has_key(''idNext''):cls .idNext = 0




这样做你想要的吗?请注意,我甚至不打扰__dict__

,因为类dict已经可用作__init__的最终参数。

类SetClassVars(类型):
.... cvars = dict(name = None,desc = None,required = True)

。 ... def __init __(cls,name,bases,classdict):

....代表名称,SetClassVars.cvars.iteritems()中的值:

.. ..如果不是在classdict中的名字:

.... setattr(cls,name,value)

.... class C(object):
.... __metaclass__ = SetClassVars

.... name =''foo''

.... class D(C):
.. .. __metaclass__ = SetClassVars

.... desc =''bar''

.... print C.name,C.desc,C.required
foo无真打印D.name,D.desc,D.required



无栏条真实

STeVe


嗯。 setattr()只进行浅层搜索。很高兴知道。


你的


如果不是dict中的名字:setattr(cls,name,value)

>
是一种更简洁/更好的写作方式


如果不是cls .__ dict __。has_key(var):setattr(cls,var,val)


我测试了一下。


好​​的,它们似乎都适用于简单类型。但是,如果我这么做:
$ blockquote class =post_quotes>

class SetClassVars(type):
.... cvars = dict(lst = [],desc = None)

.... def __init __(cls,name,bases,classdict):

.... for name,SetClassVars.cvars.iteritems()中的值:

....如果不是classdict中的名字:setattr(cls,name,value)

class C(object):
.... __ metaclass__ = SetClassVars

.... desc =''foo''

.... D级(C):
.... desc = bar

C.lst.append(''ccccc'')
D.lst.append(''dddd '')
C.lst
[''ccccc'',''dddd''] D.lst



[''ccccc'',''dddd'']


我对行为表示不满。


好​​的。因此,只有可变列表才会出现问题。我认为

错误,认为列表行为与

非变量相同。


这必须是一个新手的错误,它可能记录在某个地方。

*丁*我敢打赌,当他们定义

函数时会咬同一个人:


def myfunc(lst = []):


在简单错误时寻找复杂的元类问题

关于mutables是问题。奥卡姆对我嗤之以鼻。


谢谢。这有帮助。

t4


如果有人想在将来建立这个,那么当前的形式

并且使用的是:


导入副本


类ClassVars(类型):

classVars = dict(fields = [],longest = 0)#<<<<调整此>>>>

def __init __(cls,name,bases,dict):

的名称,ClassVars.classVars.iteritems()中的值:

如果名字不在dict中:setattr(cls,name,copy.copy(value))


class Table(object):

__metaclass__ = ClassVars

#其余课程如下......


我在2个地方使用这些类变量,并尝试,简单地,

将它们抽象为一个模块。但是我遇到了鸡蛋和鸡蛋的情况

我想使用类变量的新副本来定义

抽象类。鉴于我将在我的

应用程序中保存(2 * 3)6行代码,我认为现在继续进行。


I want to inherit fresh copies of some class variables. So I set up a
metaclass and meddle with the class variables there.

Now it would be convenient to run thru a dictionary rather than
explicitly set each variable. However getattr() and setattr() are out
because they chase the variable thru the class hierarchy.

So, I read the dictionary directly with cls.__dict__.has_key(var).
Reading works but when I go to set the object''s dictionary directly
with:

cls.__dict__[var] = val

I get the following error:

File Table.py, line 10, in __init__
if not cls.__dict__.has_key(var): cls.__dict__[var] = val
TypeError: Error when calling the metaclass bases
object does not support item assignment

Is there an easy way around this? Or am I stuck listing out the
variables one per line?

class SetClassVars(type):
cvars = dict(name=None, desc=None, required=True, minlen=1,
maxlen=25, idDown=999999999, idNext=0)
def __init__(cls, name, bases, dict):
if not cls.__dict__.has_key(''name''): cls.name = None
if not cls.__dict__.has_key(''desc''): cls.desc = None
if not cls.__dict__.has_key(''required''): cls.required = True
if not cls.__dict__.has_key(''minlen''): cls.minlen = 1
if not cls.__dict__.has_key(''maxlen''): cls.maxlen = 25
if not cls.__dict__.has_key(''idDown''): cls.idDown = 999999999
if not cls.__dict__.has_key(''idNext''): cls.idNext = 0

# It would be more convenient to loop thru a dictionary
#for var, val in SetClassVars.cvars.iteritems():

# getattr() and setattr() run thru the MRO
# which is not what I want
#if not getattr(cls, var): setattr(cls, var, val)
#if not cls.__dict__.has_key(var): setattr(cls, var, val)

# Setting the dictionary directly generates an error
#if not cls.__dict__.has_key(var): cls.__dict__[var] = val

thanks
t4

解决方案

te*********@gmail.com wrote:

I want to inherit fresh copies of some class variables. So I set up a
metaclass and meddle with the class variables there.

Now it would be convenient to run thru a dictionary rather than
explicitly set each variable. However getattr() and setattr() are out
because they chase the variable thru the class hierarchy.
getattr() does, setattr() doesn''t.
Is there an easy way around this? Or am I stuck listing out the
variables one per line?

class SetClassVars(type):
cvars = dict(name=None, desc=None, required=True, minlen=1,
maxlen=25, idDown=999999999, idNext=0)
def __init__(cls, name, bases, dict):
if not cls.__dict__.has_key(''name''): cls.name = None
if not cls.__dict__.has_key(''desc''): cls.desc = None
if not cls.__dict__.has_key(''required''): cls.required = True
if not cls.__dict__.has_key(''minlen''): cls.minlen = 1
if not cls.__dict__.has_key(''maxlen''): cls.maxlen = 25
if not cls.__dict__.has_key(''idDown''): cls.idDown = 999999999
if not cls.__dict__.has_key(''idNext''): cls.idNext = 0



Does this do what you want? Note that I don''t even bother with __dict__
since the class dict is already available as the final argument to __init__.

class SetClassVars(type): .... cvars = dict(name=None, desc=None, required=True)
.... def __init__(cls, name, bases, classdict):
.... for name, value in SetClassVars.cvars.iteritems():
.... if not name in classdict:
.... setattr(cls, name, value)
.... class C(object): .... __metaclass__ = SetClassVars
.... name = ''foo''
.... class D(C): .... __metaclass__ = SetClassVars
.... desc = ''bar''
.... print C.name, C.desc, C.required foo None True print D.name, D.desc, D.required


None bar True
STeVe


Hmm. setattr() only does a shallow search. Good to know.

Your

if not name in dict: setattr(cls, name, value)

is a more succinct/better way of writing

if not cls.__dict__.has_key(var): setattr(cls, var, val)

Which i tested a fair bit.

OK it appears that both are working for the simple types. However, if I
do:

class SetClassVars(type): .... cvars = dict(lst=[], desc=None)
.... def __init__(cls, name, bases, classdict):
.... for name, value in SetClassVars.cvars.iteritems():
.... if not name in classdict: setattr(cls, name, value)
class C(object): .... __metaclass__ = SetClassVars
.... desc = ''foo''
.... class D(C): .... desc = bar
C.lst.append(''ccccc'')
D.lst.append(''dddd'')
C.lst [''ccccc'', ''dddd''] D.lst


[''ccccc'', ''dddd'']

I get the piling on behavior.

OK. So it seems to be a problem only with the mutable list. I made the
mistake of thinking that the list behavior was the same as for
non-mutables.

This must be a newbie mistake and it is probably documented somewhere.
*Ding* I''ll bet it is the same one that bites newbies when they define
functions like:

def myfunc(lst=[]):

Looking for complicated problems with metaclasses when simple mistakes
about mutables are the issue. Occam wags his finger at me.

Thank you. That helped.
t4


If some one ever wants to build on this in the future, the current form
and use is:

import copy

class ClassVars(type):
classVars = dict(fields=[], longest=0) # <<<< adjust this >>>>
def __init__(cls, name, bases, dict):
for name, value in ClassVars.classVars.iteritems():
if name not in dict: setattr(cls, name, copy.copy(value))

class Table(object):
__metaclass__ = ClassVars
# Rest of class follows...

I use these class varaibles in 2 places and attempted, breifly, to
abstract them into a module. But I ran into a chicken and egg situation
were I wanted to use fresh copies of class variables to define the
abstracted class. Given that I''d onlly save (2*3) 6 lines of code in my
application, I figured that move on for now.


这篇关于使用元类继承类变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆