何为定制类?

Python的class允许定义许多特殊方法,可以让我们非常方便地生成特定的类。在类中应用或者重写python的特殊方法,得到的类,就是定制类。

大家都知道print的用法。见下面例子

  1. >>> lst = [2,3,4]
  2. >>> print lst
  3. [2, 3, 4]
  4. >>> class Animal(object):
  5. pass
  6.  
  7. >>> a = Animal()
  8. >>> print a
  9. <__main__.Animal object at 0x01E6E990>

为什么print都能识别出lst和p的数据类型呢?

当我们执行如下代码的时候,就知道为什么了?

  1. >>> print lst.__str__
  2. <method-wrapper '__str__' of list object at 0x01E641E8>
  3. >>> print a.__str__
  4. <method-wrapper '__str__' of Animal object at 0x01E6E990>

__str__特殊方法,能识别出每一个数据类型。如果希望类的实例print a 打印出 ‘object of Animal class’.怎么办?重新定义__str__方法。

  1. >>> class Animal(object):
  2. def __str__(self):
  3. return 'object of Animal class'
  4.  
  5. >>> a = Animal()
  6. >>> print a
  7. object of Animal class

但是有时候发现直接敲

  1. >>> a
  2. <__main__.Animal object at 0x01E6E990>

__str__不会被调用。因为当直接敲a这行代码的时候,直接调用的并不是__str__.而是__repr__.

  1. >>> class Animal(object):
  2. def __str__(self):
  3. return 'object of Animal class'
  4. __repr__ = __str__ //偷懒一下
  5.  
  6. >>> a = Animal()
  7. >>> a
  8. object of Animal class

python的特殊方法很多,这里就不做一一介绍。下面主要介绍 __slots__,__call__,@property用法。

__slots__

python是一个动态语言,任何实例可以再运行期间都能动态添加实例的属性。但是有时候,想限制实例的添加属性,就使用__slot__方法。见下面例子:

  1. >>> class Person(object):
  2. __slots__ = ('name','age')//限制只有name和age的属性
  3. def __init__(self,name,age):
  4. self.name = name
  5. self.age = age
  6.  
  7. >>> p = Person('zhangsan',25)
  8. >>> p.age
  9. 25
  10. >>> p.name
  11. 'zhangsan'
  12. >>> p.gender ='man'//直接动态赋属性gender,会出现错误
  13.  
  14. Traceback (most recent call last):
  15. File "<pyshell#42>", line 1, in <module>
  16. p.gender ='man'
  17. AttributeError: 'Person' object has no attribute 'gender'

__slot__目的是限制当前类所能拥有的属性。所以在继承的环境下,子类不受影响。

  1. >>> class Student(Person):
  2. pass
  3.  
  4. >>> s = Student('zhangsan',26)
  5. >>> s.age
  6. 26
  7. >>> s.name
  8. 'zhangsan'
  9. >>> s.gender = 'man'//可以动态添加属性
  10. >>> s.gender
  11. 'man'

所以子类Student如果想自己限制添加属性的话,也要通过__slots__来控制。

__call__

一个类的实例可以变成一个可调用的对象,只需要实现一个特殊的方法__call__就可以了。

接下来我们把Student类变成一个可调用的对象:

  1. >>> class Student(Person):
  2. def __init__(self,name,score):
  3. self.name = name
  4. self.score = score
  5.  
  6. >>> class Student(Person):
  7. def __init__(self,name,score):
  8. self.name = name
  9. self.score = score
  10. def __call__(self,age):
  11. print 'my name is %s'% self.name
  12. print 'my age is %d'% age
  13.  
  14. >>> s = Student('lixi',89)
  15. >>> s(25)
  16. my name is lixi
  17. my age is 25

有时候你会发现s(25)乍一眼感觉不出来是一个函数还是对象的实例。python语言函数和对象的实例不是区分的很明显。

@property

上述的class Student中,当修改s实例的score值时,

  1. >>> s.score = 89
  2. >>> s.score = 9999

但是这样无法检查s实例的分数有效性。目前只能这样做:

  1. >>> class Student(object):
  2. def __init__(self,name,score):
  3. self.name = name
  4. self.__score = score
  5. def set_score(self,score):
  6. if score <0 or score >100:
  7. raise ValueError('invalid score')
  8. self.__score = score
  9. def get_score(self):
  10. return self.__score
  11.  
  12. >>> s = Student('wangwu',89)
  13. >>> s.set_score(89)
  14. >>> s.set_score(9999) //非法值,ValueError
  15.  
  16. Traceback (most recent call last):
  17. File "<pyshell#75>", line 1, in <module>
  18. s.set_score(9999)
  19. File "<pyshell#71>", line 7, in set_score
  20. raise ValueError('invalid score')
  21. ValueError: invalid score

有时候觉得写s.set_score和s.get_score没有直接写s.score那么直接。有没有其他办法?既能直接的s.score又能检查score的有效性?python提供@property高阶函数这样功能需求的装饰器。

  1. >>> class Student(object):
  2. def __init__(self,name,score):
  3. self.name = name
  4. self.__score = score
  5. @property
  6. def score(self):
  7. return self.__score
  8.  
  9. @score.setter
  10. def score(self,score):
  11. if score <0 or score >100:
  12. raise ValueError('invalid score')
  13. self.__score = score
  14.  
  15. >>> s = Student('liunx',98)
  16. >>> s.score = 89
  17. >>> s.score = 9999
  18.  
  19. Traceback (most recent call last):
  20. File "<pyshell#82>", line 1, in <module>
  21. s.score = 9999
  22. File "<pyshell#79>", line 12, in score
  23. raise ValueError('invalid score')
  24. ValueError: invalid score

小结:

特殊方法:

1.任何数据实例都有特殊方法

2.特殊方法定义在class中

3.不需要直接调用

4.python的某些方法或者函数会直接调用数据实例的特殊方法

实现特殊方法:

1.重新编写用到的特殊方法

2.如果重新一些特殊方法,有些关联的特殊方法也要一并实现。例如:__setattr__,__getattr__,__delattr__

python学习第十七天 --定制类的更多相关文章

  1. Python:面向对象编程3 定制类(有更新)

    Python:面向对象编程3  定制类(有更新) ⚠️本文主要内容为对Data model相关知识点的提取学习记录.(内容来自文档和部分网页教程案例) ⚠️:这个连接指向<流畅的python&g ...

  2. Python学习第十五篇——类继承和类实例化

    学习Python类时,我们明白了类的本质,以及所谓的面向对象编程思想强调的对事物本身的属性,我们对某一类事物进行描述——采用了很多方法,这些方法描述了类的属性(比如猫科动物的眼睛,四肢,是否哺乳类等等 ...

  3. Python学习_13_继承和元类

    继承 继承的含义就是子类继承父类的命名空间,子类中可以调用父类的属性和方法,由于命名空间的查找方式,当子类中定义和父类同名属性或者方法时,子类的实例调用的是子类中的属性,而不是父类,这就形成了pyth ...

  4. 从0开始的Python学习012数据结构&对象与类

    简介 数据结构是处理数据的结构,或者说,他们是用来存储一组相关数据的. 在Python中三种内建的数据结构--列表.元组和字典.学会了使用它们会使编程变得的简单. 列表 list是处理一组有序的数据结 ...

  5. Python学习(七)面向对象 ——类和实例

    Python 面向对象 —— 类和实例 类 虽然 Python 是解释性语言,但是它是面向对象的,能够进行对象编程.至于何为面向对象,在此就不详说了.面向对象程序设计本身就很值得深入学习,如要了解,请 ...

  6. Python学习笔记之selenium 定制启动 chrome 的选项

    在自动化中,默认情况下我们打开的就是一个普通的纯净的chrome浏览器,而我们平时在使用浏览器时,经常就添加一些插件,扩展,代理之类的应用.所以使用 selenium 时,我们可能需要对 chrome ...

  7. Python学习笔记(一)类和继承的使用

    一年前就打算学Python了,折腾来折腾去也一直没有用熟练,主要是类那一块不熟,昨天用Python写了几个网络编程的示例,感觉一下子迈进了很多.这几天把学习Python的笔记整理一下,内容尽量简洁. ...

  8. python学习道路(day8note)(抽象类,类的方法,异常处理,socket编程)

    1.#面向对象 #抽象接口 === 抽象类 #就是架构师给你一个架子,你们去写,如果满足不了直接报错 #python2 print("python2---抽象类".center(2 ...

  9. python 学习笔记十七 django深入学习二 form,models

    表单 GET 和 POST 处理表单时候只会用到GET 和 POST 方法. Django 的登录表单使用POST 方法,在这个方法中浏览器组合表单数据.对它们进行编码以用于传输.将它们发送到服务器然 ...

随机推荐

  1. ACM第六周竞赛题目——B CodeForces 478B

    B - B Time Limit:1000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit Statu ...

  2. hdu 1175 连连看 DFS

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1175 解题思路:从出发点开始DFS.出发点与终点中间只能通过0相连,或者直接相连,判断能否找出这样的路 ...

  3. Java 类加载机制详解

    一.类加载器 类加载器(ClassLoader),顾名思义,即加载类的东西.在我们使用一个类之前,JVM需要先将该类的字节码文件(.class文件)从磁盘.网络或其他来源加载到内存中,并对字节码进行解 ...

  4. Wireless Password - HDU 2825(ac自动机+状态压缩)

    题目大意:有个人想破解他邻居的密码,他邻居告诉了一些关于这个密码的信息,并且给他一个单词集合,他用这些信息判断一下最少有多少种密码. 1->, 所有的密码都是有小写字母组成. 2->,密码 ...

  5. poj 1458 Common Subsequence【LCS】

    Common Subsequence Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 43132   Accepted: 17 ...

  6. System.Threading.Timer 使用

    //定义计时器执行完成后的回调函数 TimerCallback timecallback = new TimerCallback(WriteMsg); //定义计时器 System.Threading ...

  7. Android Fragment生命周期及静态加载

    一个Fragment必须总是被嵌入到一个Activity中,它的生命周期直接被其所属的宿主Activity生命周期影响,它的状态会随宿主的状态变化而变化. 要创建一个Fragment 必须创建一个Fr ...

  8. 使用XStream注解实现Java对象与XML互相转换的代码示例

    本文记录一下使用xstream这个api的注解特性对Java对象与XML字符串相互转换的一些代码示例.    我们很多人都处理过XML文件,也有很多非常成熟的第三方开源软件.如:jdom.dom4j等 ...

  9. uva 10934 Dropping water balloons(转载)

    本文转载自http://blog.csdn.net/shuangde800/article/details/11273123 题意 你有k个一模一样的水球,在一个n层楼的建筑物上进行测试,你想知道水球 ...

  10. JavaScript自动关闭窗口

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...