实例变量的Pythonic别名?
我有一个类,用来存储数据在一个列表里,主要是为了继承的需要。我想知道,除了创建获取和设置函数(也就是getter和setter)之外,还有没有更简洁的方法来给这个列表里的元素起个别名。
举个例子……
class Serializable(object):
"""Adds serialization to from binary string"""
def encode(self):
"""Pack into struct"""
return self.encoder.pack(*self)
def decode(self, data_str):
"""Unpack from struct"""
self.data = self.encoder.unpack(data_str)
return self.data
class Ping(Serializable):
encoder = Struct("!16sBBBL")
def __init__(self, ident=create_id(), ttl=TTL, hops=0, length=0):
self.data = [ident, 1, ttl, hops, length]
self.ident = property(self.data[0])
def __getitem__(self, index):
return self.data[index]
@property
def ident(self):
return self.data[0]
@ident.setter
def ident(self, value):
self.data[0] = value
@property
def protocol(self):
return self.data[1]
@protocol.setter
def protocol(self, protocol):
self.data[1]
我希望能有一个更简单的方法来引用object.ident,同时还能保持像上面那样打包和解包的能力。
3 个回答
0
如果你只是想让访问 ident
的代码变得更简短,你可以用“老式”的方法来使用“属性”。也就是说,你可以把获取和设置的函数作为参数传给它,而不是用装饰器的方式。
在这种情况下,这些函数很简单,可以用 lambda 函数来写,这样不会影响代码的可读性。
class Ping(Serializable):
encoder = Struct("!16sBBBL")
def __init__(self, ident=None, ttl=TTL, hops=0, length=0):
if ident is None:
ident = create_id()
self.data = [ident, 1, ttl, hops, length]
# The line bellow looks like garbage -
# it does not even make sense as a call to `property`
# should have a callable as first parameter
# returns an object that is designed to work as a class attribute
# self.ident = property(self.data[0])
# rather:
self.ident = ident
# this will use the property defined bellow
def __getitem__(self, index):
return self.data[index]
ident = property(lambda s: s.data[0], lambda s, v: s.data[0].__setitem__(0, v)
protocol = property(lambda s: s.data[1], lambda s, v: s.data[1].__setitem__(1, v)
2
在编程中,有时候我们会遇到一些问题,尤其是在使用某些工具或库的时候。这些问题可能会让我们感到困惑,不知道该如何解决。比如,有人可能在使用某个特定的功能时,发现它并没有按照预期工作,或者出现了错误信息。这种情况下,通常我们可以在网上寻找答案,比如在StackOverflow这样的平台上。
在这些平台上,很多人会分享他们遇到的问题和解决方案。你可以看到其他程序员是如何解决类似的问题,或者他们是如何理解某个概念的。这对于刚开始学习编程的人来说,特别有帮助,因为你可以从别人的经验中学习,避免走弯路。
总之,遇到问题时,不要害怕去寻求帮助。网络上有很多资源可以帮助你理解和解决问题,记得多多利用这些资源哦!
def alias_property(key):
return property(
lambda self: getattr(self, key),
lambda self, val: setattr(self, key, val),
lambda self: delattr(self, key))
class A(object):
def __init__(self, prop):
self.prop = prop
prop_alias = alias_property('prop')
3
如果你把你的值或者属性存储在一个字典里,效果会更好:
def __init__(self, ident=create_id(), ttl=TTL, hops=0, length=0):
self.data = {
'ident': ident,
'protocol': 1,
'ttl': hops,
'length': length,
}
然后你可以重写 __getattr__
和 __setattr__
这两个方法:
def __getattr__(self, attr):
return self.data[attr]
def __setattr__(self, attr, value):
if attr == 'data':
object.__setattr__(self, attr, value)
else:
self.data[attr] = value
这样你就可以这样做了:
>>> ping = Ping()
>>> ping.protocol
1
>>> ping.protocol = 2
>>> ping.protocol
2
如果 self.data
一定要是一个列表,你可以这样做:
class Ping(Serializable):
mapping = ('ident', 'protocol', 'ttl', 'hops', 'length')
encoder = Struct("!16sBBBL")
def __init__(self, ident=create_id(), ttl=TTL, hops=0, length=0):
self.data = [ident, 1, ttl, hops, length]
def __getitem__(self, index):
return self.data[index]
def __getattr__(self, attr):
index = self.mapping.index(attr)
return self.data[index]
def __setattr__(self, attr, value):
if attr == 'data':
object.__setattr__(self, attr, value)
else:
index = self.mapping.index(attr)
self.data[index] = value