python里面类变量count怎么做,在Python中,计算类中的变量数或阻止添加新的类变量...

In python, is there a way to prevent adding new class variables after defining the object?

For example:

class foo:

def __init__(self):

self.a = 1

self.b = 2

self.c = 3

bar = foo()

try:

bar.d = 4

except Exception, e:

print "I want this to always print"

Alternatively, is there a way to count the number of variables in an object?

class foo:

def __init__(self):

self.a = 1

self.b = 2

self.c = 3

def count(self):

...

bar = foo()

if bar.count() == 3:

print "I want this to always print"

The only way I thought of doing this was using a dictionary or list:

class foo:

def __int__(self):

self.dict = {'foo':1, 'bar':2}

self.len = 2

def chk():

return self.len == len(self.list)

However, doing this feels rather cumbersome for python. (obj.dict['foo']). I'd prefer just obj.foo if possible.

I want to have this so that I never accidentally declare a variable when I mean to change an existing one.

f = foo()

f.somename = 3

...

f.simename = 4 #this is a typo

if f.somename == 3:

solve_everything()

Thanks in advanced.

解决方案

I suggest using __setattr__ to avoid the oddities of __slots__.

You always have to be careful when messing with __setattr__, since it takes care of setting all instance attributes, including those you set in __init__. Therefore it has to have some way of knowing when to allow the setting of an attribute, and when to deny it. In this solution I've designated a special attribute that controls whether new attributes are allowed or not:

class A(object):

def __init__(self):

self.a = 1

self.b = 2

self.c = 3

self.freeze = True

def __setattr__(self, attr, value):

if getattr(self, "freeze", False) and not hasattr(self, attr):

raise AttributeError("You shall not set attributes!")

super(A, self).__setattr__(attr, value)

Testing:

a = A()

try:

a.d = 89

except AttributeError:

print "It works!"

else:

print "It doesn't work."

a.c = 42

print a.a

print a.c

a.freeze = False

a.d = 28

a.freeze = True

print a.d

Result:

It works!

1

42

28

Also see gnibblers answer that wraps this concept neatly up in a class decorator, so it doesn't clutter up the class definition and can be reused in several classes without duplicating code.

EDIT:

Coming back to this answer a year later, I realize a context manager might solve this problem even better. Here's a modified version of gnibbler's class decorator:

from contextlib import contextmanager

@contextmanager

def declare_attributes(self):

self._allow_declarations = True

try:

yield

finally:

self._allow_declarations = False

def restrict_attributes(cls):

cls.declare_attributes = declare_attributes

def _setattr(self, attr, value):

disallow_declarations = not getattr(self, "_allow_declarations", False)

if disallow_declarations and attr != "_allow_declarations":

if not hasattr(self, attr):

raise AttributeError("You shall not set attributes!")

super(cls, self).__setattr__(attr, value)

cls.__setattr__ = _setattr

return cls

And here's how to use it:

@restrict_attributes

class A(object):

def __init__(self):

with self.declare_attributes():

self.a = 1

self.b = 2

self.c = 3

So whenever you want to set new attributes, just use the with statement as above. It can also be done from outside the instance:

a = A()

try:

a.d = 89

except AttributeError:

print "It works!"

else:

print "It doesn't work."

a.c = 42

print a.a

print a.c

with a.declare_attributes():

a.d = 28

print a.d

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值