前几天一直在练手廖雪峰老师的python课程,接下来继续学习,由于面向对象编程这一课相对理论便不在此练手,直接上手面向对象高级编程。

一、使用 __slots__

  一般情况下一个class是可以绑定一个属性和方法的,例如:

#给实例绑定属性 和 方法
#绑定属性
class Student(object):
pass s = Student()
s.name = 'nihao'
print(s.name)

  绑定方法:

#绑定方法
def setAge(self, a):
self.age = a from types import MethodType
s.setAge = MethodType(setAge, s)
s.setAge(22)
print( s.age )

  给一个实例绑定一个方法,对于另外一个实例是不起作用的

  例如:

#给一个实例绑定一个方法,对于另外一个实例是不起作用的
s2 = Student()
#s2.setAge(11)

  说明:这里的s2.setAge(11)是会报错的。

  但是给class绑定方法后,所有实例均可调用

#但是给class绑定方法后,所有实例均可调用
def setScore(self, score):
self.score = score Student.setScore = setScore s.setScore(11)
print( s.score ) s2.setScore(33)
print( s2.score )

  其他的案例将函数写在class里面,任何实例都可以调用:

class Test(object):
def myFun(self, num):
self.num = num t = Test()
t.myFun(22)
print(t.num)

  总结:可以给一个实例绑定方法和属性,但是另外一个实例调用是不起作用的,除非给class绑定一个方法,或者在class里面自定义一个方法,这样才会在所有的实例中都可以调用。

  使用__slots__

  说明:__slots__ 的英文单词是槽的意思,也就是一个位置的意思。占用一个坑。__slots__的好处是可以限定一个class的实例绑定属性的个数和指定属性的标准。

       比方说我限定了一个类只能在外部绑定哪些属性名称,通过__slots__定义的就可以使用 否则定义其他属性的 class 都不认识。

  案例:

class Student(object):
__slots__ = ('name', 'age') #用tuple定义允许绑定的属性名称 s = Student()
s.name = 'cici'
print( s.name )
s.age = '18'
print( s.age )
s.score = 100
print( s.score )

  输出:

cici
18
Traceback (most recent call last):
File "/mnt/hgfs/webspace/pythonStudy/one.py", line 678, in <module>
s.score = 100
AttributeError: 'Student' object has no attribute 'score'

  由此可见,只有定义了属性名称,是可以做外部绑定的,没有定义的属性名称,是绑定不成功的。

  另外需要注意的是:__slots__只对当前类起作用,对于继承的子类是不起作用的。

二、使用@property

  通常我们通过实例去给一个实例绑定一个属性,或者修改属性的值,显然很不安全,可以通过如下案例实现:

class Student(object):

    def getScore(self):
return self._score def setScore(self, val):
if not isinstance(val, int):
raise ValueError('请输入整型')
if val <0 or val> 100:
raise ValueError('范围要在0-100直间')
self._score = val s = Student() s.setScore(44)
print( s.getScore() )

  说明:由此可见,通过设置方法,去设置参数,再通过另外一个方法去获取参数。明显比较安全些,但是这种写法稍微复杂了一点,要调用两个方法才行

  python恰好有一个即可以验证参数,有可以像普通绑定属性这样简单的方式,那就是python内置的@property装饰器 装饰器就是负责把一个方法变成属性调用的形式:
  案例:

class Student(object):

    @property
def score(self):
return self._score @score.setter
def score(self, val):
if not isinstance(val, int):
raise ValueError('score is integer')
elif val <0 or val >100:
raise ValueError('0-100')
self._score = val s = Student()
s.score = 90 print(s.score)

  输出:90

  说明:要将一个getter方法变成属性一样的调用,只需要加上@property就可以了,另外 @property 本身又创建了一个装饰器@score.setter 负责把一个setter方法变成属性赋值,这样就可以得到一个可控的属性操作了。

三、定制类

  在python中类似__xxx__的变量或则函数名说明它们是拥有特殊用途的函数。

  例如:

  __str__

  案例:

class Student(object):
def __init__(self, name):
self.name = name print( Student('cici') )

  输出:<__main__.Student object at 0x7fd703484940>

  说明:由此可见,这种输出是非常不好看的,改一下

class Student(object):
def __init__(self, name):
self.name = name
def __str__(self):
return 'Student object (name: %s)' % self.name print( Student('cici') )

  输出:Student object (name: cici)

  由此可见,__str__()方法是可以返回一个好看的字符串的,而且还可以看出实例内部的数据。

  __iter__ 

class Fib(object):
def __init__(self):
self.a, self.b = 0, 1 #初始化两个计数器 def __iter__(self):
return self #实例本身就是迭代对象 def __next__(self):
self.a, self.b = self.b, self.a+self.b #计算下一个值
if self.a > 20: #退出循环的条件
raise StopIteration()
return self.a #返回下一个值 for item in Fib():
print(item)

  输出:

1
1
2
3
5
8
13

  说明:如果一个类想要被for ... in ... 循环,类似list 或 tuple ,就必须实现一个__iter__() 方法 返回它自己,改方法返回一个迭代对象,然后,python 的 for 循环将会不间断的调用该迭代对象的 __next__() 方法,拿到循环的下一个值,直到遇到 StopIteration 错误时退出。

     __getitem__

  上面定义的Fib实例虽然可以作用于for循环,看起来类似list,但是它并不能类似list一样去使用,比如取值的时候:  

class Fib(object):
def __getitem__(self, item):
a,b = 1,1
for x in range(item):
a, b = b, a+b
return a print(Fib()[0])
print(Fib()[1])
print(Fib()[2])
print(Fib()[3])
print(Fib()[4])
print(Fib()[5])

  输出:

1
1
2
3
5
8

  说明:由此可见,若要将一个实例像list那样调用按照下标取元素,需要在定义一个__getitem__()方法。

  注意: list 有一个切片方法,但是用在类里面会报错,这是由于__getitem__()传入的参数有可能是一个int 也有可能是一个切片的对象slice,所以需要做判断:

  __getattr__

  一般情况下,如果我们调用一个类的方法或者属性,如果不存在,就会报错,例如:

class Student(object):

    def __init__(self):
self.name = 'cici' s = Student()
print( s.name )
print( s.score )

  输出:

cici
Traceback (most recent call last):
File "/mnt/hgfs/webspace/pythonStudy/one.py", line 771, in <module>
print( s.score )
AttributeError: 'Student' object has no attribute 'score'

  说明:由此可见,调用 name 的时候没有问题,而调用 score的时候说Student没有找score的元素

  通过__getattr__控制

class Student(object):

    def __init__(self):
self.name = 'cici' def __getattr__(self, item):
if item == 'score':
return 100 s = Student()
print( s.name )
print( s.score )
print( s.aaaaa )

  输出:

cici
100
None

  说明:由此可见,在类中增加了一个__getattr__ 可以自定义输出的属性,另外在次访问不存在的属性或时会友好的返回None

  __call__

  一个对象实例可以有自己的属性和方法,当我们调用实例方法时使用 instance.method() 来调用,能不能直接在实例本身上调用呢?案例

  例如:

class Student(object):
def __init__(self, name):
self.name = name def __call__(self):
return self.name s = Student('cici')
print( s() )

  输出:‘cici'

  说明:由此可见,如果像调用实例本身 s() 其实是可以调用成功的,因为这类中我们已经定义了一个__call__()方法,这样就实现了调用实例就好像调用函数一样的效果。

     那么问题就来了,如果区分它是一个对象,还是一个函数呢?更多时候,我们需要判断一个对象是否能够被调用,能够被调用的对象就是一个Callable对象

  例如:  

print( callable(Student) )

  返回:True

  所以、通过callable()函数,就可以判断这个对象是否是 可调用的 对象。

四、使用枚举类

  定义一个枚举

from enum import Enum, unique
Month = Enum('Month', ('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec')) for name, member in Month.__members__.items():
print(name, '=>', member, ',', member.value)

  输出:

Jan => Month.Jan , 1
Feb => Month.Feb , 2
Mar => Month.Mar , 3
Apr => Month.Apr , 4
May => Month.May , 5
Jun => Month.Jun , 6
Jul => Month.Jul , 7
Aug => Month.Aug , 8
Sep => Month.Sep , 9
Oct => Month.Oct , 10
Nov => Month.Nov , 11
Dec => Month.Dec , 12

  访问枚举的方法

@unique
class Weekday(Enum):
Sun = 0 # Sun的value被设定为0
Mon = 1
Tue = 2
Wed = 3
Thu = 4
Fri = 5
Sat = 6 #访问这些枚举类型的方法
day1 = Weekday.Mon
print( day1 )
print( day1.value )
print( Weekday['Thu'])
print( Weekday['Thu'].value)
print( Weekday(2) )

  输出:

Weekday.Mon
1
Weekday.Thu
4
Weekday.Tue

  可见,既可以用成员名称引用枚举常量,又可以直接根据value的值获得枚举常量。

五、使用元类

  。。。

   

  

Python基础学习(六)的更多相关文章

  1. 【Python基础学习六】函数

    1.创建函数 Python中函数的关键字def来定义. def fibs(num): f=[0,1] for i in range(1,num): f.append(f[-1]+f[-2]) retu ...

  2. Python基础学习六 操作MySQL

    python操作数据库,需要先安装模块 1.下载MySQL.Redis模块 2.解压后,在当前目录执行 python setup.py install 3.或是pycharm直接选择安装 import ...

  3. Python基础学习六 操作Redis

    import redis r = redis.Redis(host=',db=1) #set get delete setex 都是针对string类型的 k-v # r.set('louis_ses ...

  4. Day1 Python基础学习

    一.编程语言分类 1.简介 机器语言:站在计算机的角度,说计算机能听懂的语言,那就是直接用二进制编程,直接操作硬件 汇编语言:站在计算机的角度,简写的英文标识符取代二进制去编写程序,本质仍然是直接操作 ...

  5. Day1 Python基础学习——概述、基本数据类型、流程控制

    一.Python基础学习 一.编程语言分类 1.简介 机器语言:站在计算机的角度,说计算机能听懂的语言,那就是直接用二进制编程,直接操作硬件 汇编语言:站在计算机的角度,简写的英文标识符取代二进制去编 ...

  6. Python 基础学习 总结篇

    Python 基础学习总结 先附上所有的章节: Python学习(一)安装.环境配置及IDE推荐 Python学习(二)Python 简介 Python学习(三)流程控制 Python学习(四)数据结 ...

  7. Python基础学习五

    Python基础学习五 迭代 for x in 变量: 其中变量可以是字符串.列表.字典.集合. 当迭代字典时,通过字典的内置函数value()可以迭代出值:通过字典的内置函数items()可以迭代出 ...

  8. 0003.5-20180422-自动化第四章-python基础学习笔记--脚本

    0003.5-20180422-自动化第四章-python基础学习笔记--脚本 1-shopping """ v = [ {"name": " ...

  9. (一)python基础学习

    根据廖雪峰老师的python教程写一些学习总结! Python基础学习 1.使用list和tuple (1)list Python内置的一种数据类型是列表:list.list是一种有序的集合,可以随时 ...

  10. python基础学习(起步)

    目录 python基础学习(起步) 变量 常量 变量的内存管理 python垃圾回收机制 变量的其他赋值方式 今日编程小题 本人能力有限,若有偏颇之处请读者大大不吝赐教! 祝大家每天都在成长! pyt ...

随机推荐

  1. linux下向一个文件中的某行插入数据的做法

    sed -i 'ni\x' test.file        表示向test.file文件里的第n行的前面添加x内容sed -i 'na\x' test.file       表示向test.file ...

  2. 微信小程序中的组件

    前言 之前做小程序开发的时候,对于开发来说比较头疼的莫过于自定义组件了,当时官方对这方面的文档也只是寥寥几句,一笔带过而已,所以写起来真的是非常非常痛苦!! 好在微信小程序的库从 1.6.3 开始,官 ...

  3. HTTP协议基础与web服务的重定向,跳转以及请求转发

    JavaWeb中,HttpServletRequest与HttpServletResponse几乎是处理各种请求与操作必备的参数,与原始的ServletRequest/ServletResponse相 ...

  4. Visual Studio2013安装过程以及单元测试

    一.安装环境 操作系统版本:Windows10家庭中文版64位 CPU:i5-4200u  1.60GHz 硬盘内存:750G 二.安装版本 Visual Studio2013 三.安装过程 Visu ...

  5. 对于VS软件的个人评价

    因为还是一个菜鸟,对于VS这样的大软件还只能是自己个人的理解,以前用的是VC++,后来因为电脑系统更新,开始接触了VS,个人觉得还是vs2010更好用一些,作为一款windows平台应用程序的集成开发 ...

  6. Linux实践一:问题及解决

    安装ubuntu出现的问题 : 打开镜像.iso文件,v-box好像是不识别这种格式的,它识别的好像是.vdi等格式,所以要用vm虚拟机打开镜像安装 打开镜像,按照步骤安装后,安装很久后,出现问题.初 ...

  7. Python学习笔记 -- 第五章

    模块 使用模块可以提高了代码的可维护性.其次,编写代码不必从零开始.当一个模块编写完毕,就可以被其他地方引用.我们在编写程序的时候,也经常引用其他模块,包括Python内置的模块和来自第三方的模块: ...

  8. git 的安装及使用

    一.Git的安装和使用 1.1 Linux下版本库的创建 1.1.1 创建一个版本库 repository,在一个合适的地方创建一个空目录: root@zengyue:/# mkdir -p /hom ...

  9. [2017BUAA软件工程]第0次个人作业

    第一部分: 结缘计算机 1. 你为什么选择计算机专业?你认为你的条件如何?和这些博主比呢? 有时候我也问自己这个问题,是因为认识的人中有人从事这个工作并且做得很好而产生了艳羡?是因为家长一次次催逼,想 ...

  10. Oracle 控制文件管理

    控制文件是一个很小的二进制文件(10MB左右),含有数据库结构信息,包括数据文件和日志文件信息.控制文件在数据库创建时被自动创建,并在数据库发生物理变数时更新.控制文件被不断更新,在任何时候都要保证控 ...