用类存储数据
类实际上就是一个数据结构, 对于 python 而言, 它是一个类似于字典的结构. 当根据类创建了对象之后, 这个对象就有了一个数据结构, 包含一些赋值了的属性. 在这一点上, 它和其它语言的 struct 的作用是类似的: 存储数据并提供数据检索功能.
例如, 下面是史上最简单的类:
class Person: pass
pass 关键字表示这个类没有实际的逻辑体. 这里只是定义了一个类, 这个类的对象初始化时不会存放任何数据. 现在, 构造一个对象, 让它和 dict 一样存放一些数据:
- p = Person() # 构造对象
- p.name = "longshuai" # 创建对象的属性 name
- p.age = 23 # 创建对象的属性 age
现在, Person 的实例对象 p 中就存放了两个属性: p.name 和 p.age. 可以直接去检索存放在 p 中的数据:
- print(p.name) # 输出 "longshuai"
- print(p.age) # 输出 23
也可以使用 dict 来存储这些数据:
- >>> d={
- }
- >>> d["name"]="longshuai"
- >>> d["age"]=23
- >>> print(d["name"])
- longshuai
- >>> print(d["age"])
- 23
在数据存储方面, 它们的作用是完全等价的. 实际上对象 / 类在内部就是使用一个名为__dict__的 dict 类型来存放它所拥有的数据的.
- >>> p.__dict__
- {
- 'name': 'longshuai', 'age': 23
- }
__init__() 构造对象初始数据
上面的 name 和 age 属性是在构建了对象之后附加上去的, 如果想要创建对象时就存放好数据, 可以定义类的构造函数__init__(). 例如:
- class Person:
- def __init__(self,name,age):
- self.name = name
- self.age = age
然后创建对象的时候, 传递 name 参数和 age 参数即可.
- >>> p = Person("longshuai",23)
- >>> p.__dict__
- {
- 'name': 'longshuai', 'age': 23
- }
如果想定义这个类公有的数据, 可以将公有属性定义为类的属性. 比如中国人都是黄皮肤:
- class Person:
- skin = "yellow"
- def __init__(self,name,age):
- self.name = name
- self.age = age
这样每次创建 Person 的对象实例时, 每个对象都会有相同的肤色: yellow. 但注意, 这个 skin 属性是类属性, 不是对象属性, 它是存放在类的名称空间中的. 当对象真的需要这个属性的时候, 会临时去检索类的名称空间来获取. 看下面的__dict__字典即可知道:
- >>> p = Person("longshuai",23)
- >>> p.__dict__
- {
- 'name': 'longshuai', 'age': 23
- }
- >>> p.skin
- 'yellow'
setter 和 getter 方法
在面向对象的角度上考虑, 一般是不建议直接在类的外部通过 x.name 的方式赋值, 取值的. 而是定义对应的方法, 通过方法来取得对应的值. 这两类方法称为 setter,getter 方法: setter 用于赋值或设置属性值, getter 用于取得属性值.
- class Person:
- skin = "yellow"
- def __init__(self,name,age):
- self.name = name
- self.age = age
- def set(self,job):
- self.job = job
- return self
- def get(self):
- return self.name,self.age,self.job
上面的 set 方法用于设置一个新属性 job.get 用于返回对象的 3 个属性.
- >>> p = Person("longshuai",23)
- >>> p.set("manager")
- >>> name, age, job = p.get()
- >>> print([name,age,job])
- ['longshuai', 23, 'manager']
需要注意, setter 方法可以有多种类型的返回值, 常用的有 4 种:
返回设置后的值
返回设置前的值
返回对象自身
返回布尔值, 表示是否设置成功
这 4 种返回值都很常见, 特别是第三种用来串联对象方法的时候非常好用. 修改上面的 set 方法:
- class Person:
- skin = "yellow"
- def __init__(self,name,age):
- self.name = name
- self.age = age
- def set(self,job):
- self.job = job
- return self
- def get(self):
- return self.name,self.age,self.job
上面的 set() 返回 self 对象自身. 于是串联 set() 和 get():
- >>> p = Person("longshuai",23)
- >>> name,age,job = p.set("manager").get()
无论使用何种返回值方式, 都不会真正影响程序的使用. 但使用合理的返回值类型, 可能会简化代码的编写. 另外, 决定了返回值的方式后, 就不要再去修改, 因为很可能会牵一发而动全身.
上面的 getter 返回了多个值, 但一般来说 getter 只返回一个对应的属性. 比如 getname() 返回 name 属性, getage() 返回 age 属性等. 这样需要定义多个 getter 方法.
- def get_name(self):
- return self.name
- def get_age(self):
- return self.age
- def get_job(self):
- return self.job
合并 setter 和 getter
很多时候可以合并 setter 和 getter 方法. 合并的方式是判断方法的参数, 如果调用方法的时候给了参数, 就表示 setter, 没有给定参数, 就表示是 getter.
例如, 对于 job 属性:
- def set_get_job(self, job=None):
- if job:
- self.job = job
- else:
- return self.job
现在可以以给参数和不给参数两种不同的方式来调用 set_get_job() 方法:
- p = Person("longshuai", 23)
- p.set_get_job("manager") # 给了参数, 说明是 setter
- job = p.set_get_job() # 没给参数, 说明是 getter
总结
本文介绍了各种设置对象属性的方式, 属性其实就是数据, 对象 / 类就是属性的容器, 这一点很重要. 我最开始学 java 的面向对象时, 虽然对类和对象有那些教科书式的理解, 但始终没有感受到类 / 对象其实就是一种用来存储数据的数据结构. 直到学习了 Python/Perl, 我才意识到这一点, 然后理解面向对象就容易的多了.
来源: https://www.cnblogs.com/f-ck-need-u/p/10091181.html