按名称初始化、设置和获取自定义对象属性的 Pythonic 方法是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15281746/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 19:40:34  来源:igfitidea点击:

What's the Pythonic way to initialize, set and get my custom object's attributes, by name?

pythonobjectpropertiesattributes

提问by djcmm476

I'm quite new to Python and I need to make declare my own data structure, I'm a bit confused on how to do this though. I currently have:

我对 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

This isn't working, however, when I try to define an instance of the class with:

但是,当我尝试使用以下命令定义类的实例时,这不起作用:

 p1 = Particle(mass, position, velocity, force)

Every value just ends up as a (0.0, 0.0) (which is the value for velocity and force).

每个值都以 (0.0, 0.0) 结束(这是速度和力的值)。

Could someone explain where I'm going wrong, all I need from the data structure is to be able to pull the data out of it, nothing else. (edit: actually, sorry, I will have to change them a bit later on)

有人可以解释我哪里出错了,我需要从数据结构中提取数据,没有别的。(编辑:实际上,抱歉,稍后我将不得不更改它们)

Thanks

谢谢

采纳答案by David Marx

First off, you should understand that __getitem__is syntactic sugar. It's nice to have, but if you don't need it, don't use it. __getitem__and __setitem__are basically if you want to be able to access items from your object using bracket notation like:

首先,你应该明白这__getitem__是语法糖。拥有它很好,但如果您不需要它,请不要使用它。__getitem__并且__setitem__基本上如果您希望能够使用括号表示法访问对象中的项目,例如:

p= Particle(foo)
bar = p[0]

if you don't need to this, don't worry about it.

如果您不需要这个,请不要担心。

Now, onto everything else. It looks like you've got the main characteristics you want your object to carry around in your __init__definition, which is fine. Now you need to actually bind those values onto your object using self:

现在,到其他一切。看起来您已经获得了希望对象在__init__定义中包含的主要特征,这很好。现在您需要使用self以下命令将这些值实际绑定到您的对象上:

class Particle:
    def __init__(self, mass, position, velocity, force):
        self.mass = mass
        self.position = position
        self.velocity = velocity
        self.force = force

That's really it. You can now access these values using dot notation, like so:

真的是这样。您现在可以使用点表示法访问这些值,如下所示:

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

One of the nice things we get out of this is that if we ask python what pis, it will tell you that it is an instance of the Particletype, like so:

我们从中得到的好处之一是,如果我们问 python 是什么p,它会告诉你它是该Particle类型的一个实例,如下所示:

in [1]: p
out[1]: <__main__.Particle instance at 0x03E1fE68>

In theory, when you work with objects like this you want there to be a "layer of abstraction" between the user and the data such that they don't access or manipulate the data directly. To do this, you create functions (like you tried to do with __getitem__) to mediate interactions between the user and the data through class methods. This is nice, but often not necessary.

理论上,当您使用这样的对象时,您希望在用户和数据之间有一个“抽象层”,这样他们就不会直接访问或操作数据。为此,您需要创建函数(就像您尝试使用__getitem__)通过类方法来调解用户和数据之间的交互。这很好,但通常没有必要。

In your simpler case, to update the values of these attributes, you can just do it directly the same way we accessed them, with dot notation:

在您更简单的情况下,要更新这些属性的值,您可以直接按照我们访问它们的方式进行操作,并使用点表示法:

in [2]: p.mass
out[2]: 0

in [3]: p.mass = 2 
in [4]: p.mass
out[4]: 2

You might have figured this out already, but there's nothing magical about the __init__function, or even the classdefinition (where you would/should generally be defining most of your class's attributes and methods). Certain kinds of objects are pretty permissive about allowing you to add attributes whenever/wherever you want. This can be convenient, but it's generally very hacky and not good practice. I'm not suggesting that you do this, just showing you that it's possible.

您可能已经想到了这一点,但是__init__函数,甚至class定义(您通常会/应该在其中定义类的大部分属性和方法)并没有什么神奇之处。某些类型的对象允许您随时随地添加属性。这可能很方便,但它通常非常笨拙并且不是好的做法。我不是建议你这样做,只是告诉你这是可能的。

in [5]: p.newattr ='foobar!'
in [6]: p.newattr
out[6]: 'foobar!'

Weird right? If this makes your skin crawl... well, maybe it should. But it is possible, and who am I to say what you can and can't do. So that's a taste of how classes work.

很奇怪吧?如果这让你的皮肤爬行......好吧,也许它应该。但这是可能的,我是谁说你能做什么不能做什么。这就是类的工作原理。

回答by tqjustc

you can just put this class definition ahead before you use it. If you want to declare it, check this site: http://www.diveintopython.net/getting_to_know_python/declaring_functions.html

你可以在使用它之前把这个类定义放在前面。如果要声明,请查看此站点:http: //www.diveintopython.net/getting_to_know_python/declaring_functions.html

By the way, your question is similar to this post: Is it possible to forward-declare a function in Python?and also this post: Is it possible to use functions before declaring their body in python?

顺便说一句,你的问题类似于这篇文章:Is it possible to forward-declare a function in Python? 还有这篇文章:在python中声明函数体之前是否可以使用函数?

回答by Waleed Khan

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

If you want to pretend your class has properties, you can use the @propertydecorator:

如果你想假装你的类有属性,你可以使用@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

回答by Jon Clements

Seems like collections.namedtupleis what you're after:

似乎collections.namedtuple是你所追求的:

from collections import namedtuple

Particle = namedtuple('Particle', 'mass position velocity force')
p = Particle(1, 2, 3, 4)
print p.velocity

回答by neilr8133

If you justneed to store some attribute values (similar to a C-language struct), you can just do:

如果您需要存储一些属性值(类似于 C 语言struct),您可以这样做:

class myContainer(object):
    pass  # Do nothing

myContainerObj = myContainer()
myContainerObj.storedAttrib = 5
print myContainerObj.storedAttrib