看看下面的代码片段:
Array
(
[0] => Array
(
[0] => Array
(
[name] => one
[number] => 051
)
[1] => Array
(
[name] => two
[number] => 052
)
[2] => Array
(
[name] => three
[number] => 053
)
)
[1] => Array
(
[0] => Array
(
[name] => four
[number] => 061
)
[1] => Array
(
[name] => five
[number] => 062
)
)
)
我为所有面孔创建了吸气剂和吸气剂。有没有办法通过动态创建getter和setter来使代码更紧凑?
答案 0 :(得分:2)
以下代码假定您
有理由拥有self.faces
字典,而不是直接在实例上设置front
这样的属性
和/或想为self.faces
中的键实现一些有意义的getter和setter逻辑。
否则,此练习将毫无意义,因为正如Corentin Limier指出的那样,您只需设置self.front = Face(1)
,依此类推。
您可以使用描述符,保存面部名称的类变量和类装饰器。将描述符视为可重用的属性。
在下面的示例代码中,我向num
和Face
的面部添加了'side'
实例变量,只是为了演示。
class FaceDescriptor:
def __get__(self, instance, owner):
# your custom getter logic
# dummy implementation
if instance is not None:
return instance.faces[self.face]
def __set__(self, instance, value):
# your custom setter logic
# dummy implementation
instance.faces[self.face] = value
def set_faces(cls):
for face in cls._faces:
desc = FaceDescriptor()
desc.face = face
setattr(cls, face, desc)
return cls
class Face():
def __init__(self, num):
self.num = num
@set_faces
class Cube():
_faces = ['front', 'side']
def __init__(self):
self.faces = {face:Face(i) for i, face in enumerate(self._faces, 1)}
实际情况:
>>> c = Cube()
>>> c.front.num
1
>>> c.side.num
2
>>> c.front = 'stuff'
>>> c.front
'stuff'
>>> c.faces
{'front': 'stuff', 'side': <__main__.Face at 0x7fd0978f37f0>}
答案 1 :(得分:0)
假设这是您课堂上的全部工作,您可以做类似的事情
class Cube:
...
def __getattr__(self, name):
return self.faces[name]
def __setattr__(self, name, value):
self.faces[name] = value
答案 2 :(得分:0)
如果您确实想这样做,可以使用__getattr__
和__setattr__
:
class Cube:
...
def __getattr__(self, item):
return self.faces[item]
def __setattr__(self, item, value):
self.faces[item] = value
但是当您在front
中设置__init__
时,您也可以使其成为普通会员...
答案 3 :(得分:0)
您的代码是多余的,因为实例属性已存储在词典中,该词典是 __ dict __ 属性。我认识到您专注于用更少的行编写代码。保持自己的成长是一个很好的挑战,但是从长远来看,您应该专注于代码的清晰度。
这是不使用属性即可编写代码的简单方法:
df[['C','D']] = df[['A','B']].shift()
df.loc[(df[['C','D']] == 0).all(1), ['C','D']] = np.nan
df.ffill().fillna(0).astype(int)
A B C D
0 1 1 0 0
1 0 0 1 1
2 2 3 1 1
3 0 0 2 3
4 0 0 2 3
5 5 4 2 3
6 0 3 5 4
7 0 0 0 3
这是封装的宗旨,您应该将“属性”隐藏在“属性”之后。即使在python中没有强烈执行此操作,执行此操作也不是一个坏主意。这是执行此操作的正确方法:
class Face():
pass
class Cube():
def __init__(self):
self.front = Face()
self.rear = Face()
要在最后回答您的问题,是的,您可以动态创建属性。 https://stackoverflow.com/a/1355444/3368572
但是请记住,应该为特殊情况保留编写动态代码的步骤,因为这会使IDE更加难以遵循程序的流程。如果您按预期使用约定,那么您的代码将对人和您的IDE变得不言自明。