无需调用类创建对象

21 投票
6 回答
42448 浏览
提问于 2025-04-17 10:44

在matlab中,我可以通过以下方式创建一个结构数组(struct)。

person.name = 'Mike';
person.age = 25;
person.gender = 'male';

这里的person在创建这个结构之前并没有定义。当我尝试在python中这样做时,它给我报错。

name 'person' is not defined

在python中有没有类似的做法呢?谢谢。

补充说明:我刚接触python,脑子里还是在想matlab。我遇到的问题是,我有一个函数需要接收多个输入(超过40个),所以我不想写成function(input1,input2,...,input40),而是想写成function(input),其中input包含input.1, input.2,..., input.40。

6 个回答

18

Python 3.3 新增了一个叫做 SimpleNamespace 的类

跟普通的对象不同,使用 SimpleNamespace 你可以随意添加或删除属性。如果用关键字参数来初始化一个 SimpleNamespace 对象,这些参数会直接被加入到它的命名空间里。

SimpleNamespace 可以用来替代 class NS: pass。不过,如果你需要一个结构化的记录类型,建议使用 namedtuple()。

下面是一个使用 SimpleNamespace 的例子:

from types import SimpleNamespace

person = SimpleNamespace(name='Mike', age=25, gender='male')
print(person)

输出结果:

namespace(age=25, gender='male', name='Mike')

from types import SimpleNamespace

person = SimpleNamespace()
person.name = 'Mike'
person.age = 25
person.gender = 'male'

print(person)

输出结果:

namespace(age=25, gender='male', name='Mike')

32

在Python中,你可以动态地给一个对象添加成员,但有两个条件:(1) 名字必须已经存在(也就是说,必须先给它赋值),(2) 它必须和某个类的实例绑定在一起。为了做到这一点,你可以先创建一个空的类:

class Empty:
    pass        # empty statement otherwise the class declaration cannot succeed

然后创建这个类的一个实例,并把它赋值给你的变量

person = Empty()

接着你就可以添加你想要的数据了

person.name = 'Mike'
person.age = 25
person.gender = 'male'

另一方面,如果你不需要一个“普通”类提供的额外功能,只是想以键值对的方式存储一些数据,那么你可能更应该使用字典。

person={}
person['name']='Mike'
person['age']=25
person['gender']='male'

(注意,至少在Python 2.7之前,这主要只是风格或语法上的区别,因为实例成员在底层是通过字典来实现的)

一般来说,当你需要实例化多个以相同方式创建的对象时,你应该使用类(通常在类的构造函数中会给成员赋值;之后再添加成员通常会让代码变得难以理解),否则就用字典。

19

在Python中,当你开始给一个对象添加属性时,它不会自动创建一个容器对象。如果Matlab允许这样做,那我觉得Matlab有点问题。想象一下:

person.name = "Mike"
persom.age  = 25
person.sex  = "Male"

现在我们有两个对象,personpersom,而person没有age这个属性,而且没有任何提示说明这个问题。后来你尝试打印person.age,希望Matlab能报错……但可能是在你犯错的两页之后才会提醒你。

一个类本身可以用作容器或命名空间。你不需要实例化它,如果你只是想要一堆属性,这样做可以省去一些输入的麻烦。

class sex:
    male   = "M"
    female = "F"

class person:
    name = "Mike"
    age  = 25
    sex  = sex.male

要访问或修改这些属性,你可以用person.name等方式。

注意,我也用类来表示sex,这是为了说明这样做的一个好处:它能保持数据值的一致性(你不用记得是用“男”还是“男性”或“male”),而且可以避免拼写错误(比如Python会对sex.mlae报错,但对字符串“mlae”不会报错,如果你之后要和“male”比较,后者会失败)。

当然,在这种类定义中,你仍然有可能拼错nameagesex。所以你可以把类当作模板来使用,并进行实例化。

class Person:
    def __init__(self, name, age=None, sex=None):
        self.name, self.age, self.sex = name, age, sex

现在当你这样做时:

person = Person("Mike", 25, sex.male)

或者如果你想记录所有这些参数是什么:

person = Person("Mike", age=25, sex=sex.male)

那么几乎不可能出现一个属性名拼错的对象。如果你搞错了,Python会在你出错的地方给你一个错误提示。这就是选择这种方式的一个原因。

撰写回答