我对Python很陌生,我需要声明我自己的数据结构,但我对如何做到这一点有点困惑。我目前有:
class Particle:
def __init__(self, mass, position, velocity, force):
self.mass = mass
self.position, self.velocity, self.force = position, velocity, force
def __getitem__(self, mass):
return self.mass
def __getitem__(self, position):
return self.position
def __getitem__(self, velocity):
return self.velocity
def __getitem__(self, force):
return self.force
但是,当我尝试使用:
定义类的实例时,这不起作用 p1 = Particle(mass, position, velocity, force)
每个值最终都是(0.0,0.0)(这是速度和力的值)。
有人可以解释我出错的地方,我需要的数据结构就是能够从中提取数据,没有别的。 (编辑:实际上,对不起,稍后我将不得不改变它们)
由于
答案 0 :(得分:20)
首先,你应该明白__getitem__
是语法糖。很高兴有,但如果你不需要它,不要使用它。 __getitem__
和__setitem__
基本上是您希望能够使用括号表示法从对象访问项目,如:
p= Particle(foo)
bar = p[0]
如果你不需要这个,不要担心。
现在,到其他一切。看起来您已经在__init__
定义中获得了希望对象随身携带的主要特征,这很好。现在,您需要使用self
实际将这些值绑定到对象上:
class Particle:
def __init__(self, mass, position, velocity, force):
self.mass = mass
self.position = position
self.velocity = velocity
self.force = force
真的是这样。您现在可以使用点表示法访问这些值,如下所示:
mass,pos,vel,f = 0,0,0,0 # just for readability
p = Particle(mass,pos,vel,f)
print p.mass, p.position, p.velocity, p.force
我们得到的一个好处是,如果我们问python是什么p
,它会告诉你它是Particle
类型的一个实例,如下所示:
in [1]: p
out[1]: <__main__.Particle instance at 0x03E1fE68>
理论上,当你使用这样的对象时,你希望在用户和数据之间存在“抽象层”,这样他们就不会直接访问或操纵数据。为此,您可以创建函数(就像您尝试使用__getitem__
一样)来通过类方法调解用户和数据之间的交互。这很好,但通常没有必要。
在更简单的情况下,要更新这些属性的值,您可以直接以与我们访问它们相同的方式执行此操作,使用点表示法:
in [2]: p.mass
out[2]: 0
in [3]: p.mass = 2
in [4]: p.mass
out[4]: 2
你可能已经想到了这一点,但是__init__
函数,甚至class
定义(你通常应该/通常应该定义你的类的大部分属性和方法)都没有什么神奇之处。某些类型的对象非常宽松,允许您随时随地添加属性。这可能很方便,但通常非常hacky并且不是很好的做法。我不是建议你这样做,只是告诉你它是可能的。
in [5]: p.newattr ='foobar!'
in [6]: p.newattr
out[6]: 'foobar!'
奇怪吧?如果这让你的皮肤爬行......好吧,也许它应该。但这是可能的,我应该说出你能做什么,不能做什么。这就是了解课程的运作方式。
答案 1 :(得分:8)
class Particle:
def __init__(self, mass, position, velocity, force):
self.mass = mass
self.position = position
self.velocity = velocity
self.force = force
particle = Particle(1, 2, 3, 4)
print(particle.mass) # 1
如果你想假装你的班级有属性,你可以使用@property
装饰者:
class Particle:
def __init__(self, mass, position, velocity, force):
self.mass = mass
self.position = position
self.velocity = velocity
self.force = force
@property
def acceleration(self):
return self.force / self.mass
particle = Particle(2, 3, 3, 8)
print(particle.acceleration) # 4.0
答案 2 :(得分:4)
似乎collections.namedtuple
就像你所追求的那样:
from collections import namedtuple
Particle = namedtuple('Particle', 'mass position velocity force')
p = Particle(1, 2, 3, 4)
print p.velocity
答案 3 :(得分:1)
您可以在使用之前将此类定义放在前面。如果您要申报,请查看此网站:http://www.diveintopython.net/getting_to_know_python/declaring_functions.html
顺便提一下,您的问题与此帖相似:Is it possible to forward-declare a function in Python?以及此帖:Is it possible to use functions before declaring their body in python?
答案 4 :(得分:0)
如果你 需要存储一些属性值(类似于C语言struct
),你可以这样做:
class myContainer(object):
pass # Do nothing
myContainerObj = myContainer()
myContainerObj.storedAttrib = 5
print myContainerObj.storedAttrib
答案 5 :(得分:0)
在 Python 3.7+ 中有数据类库。该库将允许您创建自己的类以使用装饰器 @dataclass
快速保存数据。
@dataclass
装饰器可让您快速定义主要用于保存数据的类并向其添加功能。
您的问题的数据类可能如下实现。我提供了类型提示和默认值,您可能也会发现它们很有帮助。
from dataclasses import dataclass
@dataclass
class Particle:
mass: float
position: float
velocity: float = 0.0
force: float = 0.0
Here is a useful article 解释了如何在 Python 3.7+ 和其他一些特性中使用数据类。