python学习第十七天 --定制类

何为定制类?

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

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

>>> lst = [2,3,4]
>>> print lst
[2, 3, 4]
>>> class Animal(object):
    pass

>>> a = Animal()
>>> print a
<__main__.Animal object at 0x01E6E990>

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

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

>>> print lst.__str__
<method-wrapper ‘__str__‘ of list object at 0x01E641E8>
>>> print a.__str__
<method-wrapper ‘__str__‘ of Animal object at 0x01E6E990>

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

>>> class Animal(object):
    def __str__(self):
        return ‘object of Animal class‘

>>> a = Animal()
>>> print a
object of Animal class

但是有时候发现直接敲

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

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

>>> class Animal(object):
    def __str__(self):
        return ‘object of Animal class‘
    __repr__ = __str__ //偷懒一下

>>> a = Animal()
>>> a
object of Animal class

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

__slots__

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

>>> class Person(object):
    __slots__ = (‘name‘,‘age‘)//限制只有name和age的属性
    def __init__(self,name,age):
        self.name = name
        self.age = age

>>> p = Person(‘zhangsan‘,25)
>>> p.age
25
>>> p.name
‘zhangsan‘
>>> p.gender =‘man‘//直接动态赋属性gender,会出现错误

Traceback (most recent call last):
  File "<pyshell#42>", line 1, in <module>
    p.gender =‘man‘
AttributeError: ‘Person‘ object has no attribute ‘gender‘

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

>>> class Student(Person):
    pass

>>> s = Student(‘zhangsan‘,26)
>>> s.age
26
>>> s.name
‘zhangsan‘
>>> s.gender = ‘man‘//可以动态添加属性
>>> s.gender
‘man‘

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

__call__

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

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

>>> class Student(Person):
    def __init__(self,name,score):
        self.name = name
        self.score = score

>>> class Student(Person):
    def __init__(self,name,score):
        self.name = name
        self.score = score
    def __call__(self,age):
        print ‘my name is %s‘% self.name
        print ‘my age is %d‘% age

>>> s = Student(‘lixi‘,89)
>>> s(25)
my name is lixi
my age is 25

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

@property

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

>>> s.score = 89
>>> s.score = 9999

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

>>> class Student(object):
    def __init__(self,name,score):
        self.name = name
        self.__score = score
    def set_score(self,score):
        if score <0 or score >100:
            raise ValueError(‘invalid score‘)
        self.__score = score
    def get_score(self):
        return self.__score

>>> s = Student(‘wangwu‘,89)
>>> s.set_score(89)
>>> s.set_score(9999) //非法值,ValueError

Traceback (most recent call last):
  File "<pyshell#75>", line 1, in <module>
    s.set_score(9999)
  File "<pyshell#71>", line 7, in set_score
    raise ValueError(‘invalid score‘)
ValueError: invalid score

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

>>> class Student(object):
    def __init__(self,name,score):
        self.name = name
        self.__score = score
    @property
    def score(self):
        return self.__score

    @score.setter
    def score(self,score):
        if score <0 or score >100:
            raise ValueError(‘invalid score‘)
        self.__score = score

>>> s = Student(‘liunx‘,98)
>>> s.score = 89
>>> s.score = 9999

Traceback (most recent call last):
  File "<pyshell#82>", line 1, in <module>
    s.score = 9999
  File "<pyshell#79>", line 12, in score
    raise ValueError(‘invalid score‘)
ValueError: invalid score

小结:

特殊方法:

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

2.特殊方法定义在class中

3.不需要直接调用

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

实现特殊方法:

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

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

时间: 2024-08-24 14:52:32

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

Python学习笔记_Chapter 6定制数据对象

1. 有用的BIF a. 判断字符串中是否包含子字符串 1 if s_a in s_b: b. pop() 描述:从指定的列表位置删除并返回一个数据项. 1 (sarah_name,sarah_dob)=l_rah.pop(0),l_rah.pop(0) 2 #pop(0)中0位置为list中第一个数据项 3 #第一次执行pop赋值给sarah_name c. strip() 输入的是字符串,返回的是列表 d.open 读文件时可以多种方式打开文件,取出的数据是不同的,可以是文本也可以是二进制.

Python学习_13_继承和元类

继承 继承的含义就是子类继承父类的命名空间,子类中可以调用父类的属性和方法,由于命名空间的查找方式,当子类中定义和父类同名属性或者方法时,子类的实例调用的是子类中的属性,而不是父类,这就形成了python中的多态: def SuperClass:? ? def a_method:? ? ? ? passdef SubClass(SuperClass):? ? def a_method:? ? ? ? passobj = SubClass()obj.a_method() 当obj调用一个方法时,先

python基本知识(八):定制类,双下划线方法

'''定制类: 1. 双下划线属性__attr__ 2. 元类metaclass''' # 综述 '''iterable/iterator:1. __iter__(): return iterable_obj 1) 实现了该方法的对象叫iterable 2) iter(obj)会调用该方法, 生成一个迭代器iterator 2. __next__(): 指明迭代器怎么返回值 1) next(iterator)会返回一个值, 直到所有的值都返回了报错StopIteration 2) for.. i

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

学习地址:http://blog.csdn.net/vinson0526/article/details/51850929 使用 selenium 时,我们可能需要对 chrome 做一些特殊的设置,以完成我们期望的浏览器行为,比如阻止图片加载,阻止JavaScript执行 等动作.这些需要 selenium的 ChromeOptions 来帮助我们完成 什么是 chromeoptions chromeoptions 是一个方便控制 chrome 启动时属性的类.通过 selenium 的源码,

Python 进阶(五)定制类

__str__和__repr__ 如果要把一个类的实例变成 str,就需要实现特殊方法__str__(): class Person(object): def __init__(self, name, gender): self.name = name self.gender = gender def __str__(self): return '(Person: %s, %s)' % (self.name, self.gender) 现在,在交互式命令行下用 print 试试: >>>

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

1.#面向对象 #抽象接口 === 抽象类 #就是架构师给你一个架子,你们去写,如果满足不了直接报错 1 #python2 2 print("python2---抽象类".center(20,'#')) 3 import abc #需要在python2中测试,如果直接运行会报错 4 #因为没有调用send方法 5 class Alert(object): 6 '''报警基类''' 7 __metaclass__ = abc.ABCMeta 8 @abc.abstractmethod 9

python学习笔记之面向对象、类以及I/O操作

一.I/O 操作: open(name[,mode]) 等价于file(name[,mode]) 模式说明: r 打开只读文件,该文件必须存在. r+ 打开可读写的文件,该文件必须存在. w 打开只写文件,若文件存在则文件长度清为0,即该文件内容会消失.若文件不存在则建立该文件. w+ 打开可读写文件,若文件存在则文件长度清为零,即该文件内容会消失.若文件不存在则建立该文件. a 以附加的方式打开只写文件.若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾,即文件原先的内容会被

Python学习(十七)—— 数据库(二)

一. 数据库管理软件的由来 基于我们之前所学,数据要想永久保存,都是保存于文件中,毫无疑问,一个文件仅仅只能存在于某一台机器上.如果我们暂且忽略直接基于文件来存取数据的效率问题,并且假设程序所有的组件都运行在一台机器上,那么用文件存取数据,并没有问题. 但是很不幸,上述假设存在以下几个问题...... 1.程序所有的组件就不可能运行在一台机器上 #因为这台机器一旦挂掉则意味着整个软件的崩溃,并且程序的执行效率依赖于承载它的硬件,而一台机器机器的性能总归是有限的,受限于目前的硬件水平,就一台机器的

python 学习(二)--关于类

1.没有权限控制,在类方法或变量前加 "__" 两下划线,则变为"私有"变量(实际通过_<类名>__<变量或方法名> 可以访问) 2.类的若干自动触发的内置方法: __new__(cls[, ...])      //该方法返回一个本类的实例,传入的参数会原封不动传递给 __init__() 方法. 该方法一般在继承一个不可修改的类时使用,例如 str class CapStr(str): def __new__(cls, string):