用类存储数据

类实际上就是一个数据结构,对于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'

但注意,按照面向对象的封装原则,在类中定义类变量属性是不合理的,因为要在外部访问它需要通过x.y的方式,这意味着打开了封装好的"黑匣子",暴露了属性。除非真的有需要,否则可以将类变量的定义放进构造函数__init__()中,这样每个初始化的对象都会有该属性。

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种:

  1. 返回设置后的值
  2. 返回设置前的值
  3. 返回对象自身
  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

python的属性管理

上面解释了各种setter、getter的方式,还解释了将它们进行合并。

实际上在python中访问、设置、删除对象属性的时候,大概有以下几种方式:

  1. 使用内置函数getattr()、setattr()和delattr()
  2. 自己编写getter()setter()deleter()方法
  3. 重载__getattr__()__setattr__()__delattr__()运算符,这决定了x.y的访问、赋值方式以及del x.y的方式
  4. 使用__getattribute__()方法
  5. 使用描述符协议
  6. 使用property协议,它是一种特殊的描述符

这些还未介绍到的属性管理方式,在后面的文章中会逐渐展开解释。

总结

本文介绍了各种设置对象属性的方式,属性其实就是数据,对象/类就是属性的容器,这一点很重要。我最开始学java的面向对象时,虽然对类和对象有那些教科书式的理解,但始终没有感受到类/对象其实就是一种用来存储数据的数据结构。直到学习了Python/Perl,我才意识到这一点,然后理解面向对象就容易的多了。

Python面向对象基础:设置对象属性的更多相关文章

  1. Python面向对象基础:编码细节和注意事项

    在前面,我用了3篇文章解释python的面向对象: 面向对象:从代码复用开始 面向对象:设置对象属性 类和对象的名称空间 本篇是第4篇,用一个完整的示例来解释面向对象的一些细节. 例子的模型是父类Em ...

  2. Python 面向对象之一 类与属性

    Python 面向对象之 类与属性 今天接触了一下面向对象,发现面向对象和之前理解的简直就是天壤之别,在学Linux的时候,一切皆文件,现在学面向对象了,so,一切皆对象. 之前不是一直在学的用面向函 ...

  3. C#通过属性名字符串获取、设置对象属性值

    之前理工项目从这个博客找到了相对应的方法:C#通过属性名字符串获取.设置对象属性值 https://www.cnblogs.com/willingtolove/p/12198871.html

  4. Python 面向对象基础知识

    面向对象基础知识 1.什么是面向对象编程? - 以前使用函数 - 类 + 对象 2.什么是类什么是对象,又有什么关系? class 类: def 函数1(): pass def 函数2(): pass ...

  5. 十六、python面向对象基础篇

    面向对象基础: 在了解面向对象之前,先了解下变成范式: 编程范式是一类典型的编程风格,是一种方法学 编程范式决定了程序员对程序执行的看法 oop中,程序是一系列对象的相互作用 python支持多种编程 ...

  6. 1.Python面向对象基础

    面向对象(OOP) 面向对象编程--object oriented programming 简写 OOP   面向过程和面向对象的区别: 面向过程: 1.把完成某一个需求的所有步骤从头到尾逐步实现 2 ...

  7. Python 面向对象 基础

    编程范式概述:面向过程 和 面向对象 以及函数式编程 面向过程:(Procedure Oriented)是一种以事件为中心的编程思想. 就是分析出解决问题所需要的步骤,然后用函数把这些步骤一步一步实现 ...

  8. python面向对象基础

    面向对象基础 1. 简述 编程方式: 面向过程: 根据代码在脚本的堆叠顺序,从上到下依次执行 函数式编程:将相同功能的代码封装到函数中,直接调用即可,减少代码重复性 面向对象:对函数进行分类和封装,将 ...

  9. Python 面向对象基础

    面向对象编程——Object Oriented Programming,简称OOP,是一种程序设计思想.OOP把对象作为程序的基本单元,一个对象包含了数据和操作数据的函数. 面向过程的程序设计把计算机 ...

随机推荐

  1. Codeforces Educational Codeforces Round 44 (Rated for Div. 2) E. Pencils and Boxes

    Codeforces Educational Codeforces Round 44 (Rated for Div. 2) E. Pencils and Boxes 题目连接: http://code ...

  2. 解决maven在build时下载文件卡死问题

    1.停止build 2.cd ~/.m2/repository 3.在这个目录下找到你要下载的文件,然后查看是否有个同名文件带一个.lock后缀 4.rm -f   xxxx.lock 5.重新bui ...

  3. java(二)Web部分

    2.1.1讲一下http get和post请求的区别? GET和POST请求都是http的请求方式,用户通过不同的http的请求方式完成对资源(url)的不同操作.GET,POST,PUT,DELET ...

  4. TCP的客户端搭建

    一.设计目标 之前已经写过了TCP服务器原理及通过visual studio 验证 SOCKET编程:搭建一个TCP服务器,这里我们搭建一个TCP客户端界面并对各功能进行实现.设计效果如下: 二.实验 ...

  5. CCNA学前基础一

    网络设备: 集线器:集线器就是一种采用共享式工作状态的设备.Hub将信号放大后传输给其他端口,即传输线路是共享的. 交换机:用于连接终端设备,和基本的安全功能还有广播域的隔离.优点实现多用户同时访问, ...

  6. shiro认证流程

    创建测试工程 加入shiro-core的jar包及其依赖包 与其它java开源框架类似,将shiro的jar包加入项目就可以使用shiro提供的功能了.shiro-core是核心包必须选用,还提供了与 ...

  7. 算法与数据结构(一) 线性表的顺序存储与链式存储(Swift版)

    温故而知新,在接下来的几篇博客中,将会系统的对数据结构的相关内容进行回顾并总结.数据结构乃编程的基础呢,还是要不时拿出来翻一翻回顾一下.当然数据结构相关博客中我们以Swift语言来实现.因为Swift ...

  8. Jenkins获取运行job的用户名

    1. Jenkins获取运行job的用户名 需要安装user build vars plugin 插件,然后就可以取到$BUILD_USER_ID变量. user build vars plugin下 ...

  9. 「ZJOI2018」历史(LCT)

    「ZJOI2018」历史(LCT) \(ZJOI\) 也就数据结构可做了-- 题意:给定每个点 \(access\) 次数,使轻重链切换次数最大,带修改. \(30pts:\) 挺好想的.发现切换次数 ...

  10. Javascript高级编程学习笔记(24)—— 函数表达式(2)闭包

    昨天的文章中主要记录了,函数表达式与函数声明的区别 以及在JS中如何安全地使用递归 那么既然要深入地理解JS中的函数,闭包就是一个绕不开的概念 闭包 JS高编一书中对闭包的概念定义如下: 闭包是指有权 ...