Python面向对象-定制方法
Python中的class可以定义许多定制方法,可以让我们方便的生成特定的类。
我们之前介绍了__slots__、__len__(),python中还有许多这样的特殊函数:
__str__
>>> class Student(object):
... def __init__(self,name):
... self.name = name
...
>>> print(Student('wc'))
<__main__.Student object at 0x035F3630>
上面我们定义了一个普通的Student类,打印出的是一堆<__main__.Student object at 0x035F3630> 。如何自定义打印的内容呢?比如我们关心的"WC"呢。这时__str__()派上用场了:
>>> class Student(object):
... def __init__(self,name):
... self.name = name
... def __str__(self):
... return '%s'%self.name
...
>>> print(Student('wc'))
wc
在看看我们直接调用变量会是什么情况:
>>> s = Student('wc')
>>> s
<__main__.Student object at 0x035F3AB0>
当我们直接调用变量的时候,怎么自定义打印的内容呢?使用__repr__()函数:
>>> class Student(object):
... def __init__(self,name):
... self.name = name
... def __str__(self):
... return '%s'%self.name
... def __repr__(self):
... return '%s'%self.name
...
>>> print(Student('wc'))
wc
>>> s = Student('wc')
>>> s
wc
一般来说,__str__和__repr__定义的内容是一样的,只是前者是给用户看的,后者给开发者看的。
__iter__
之前我们介绍过可迭代对象:如果我们想让一个类可以被for……in循环,就必须实现方法__iter__()方法。该方法返回一个迭代对象。下面写一个模仿输出斐波拉契数列的Fib类:
>>> 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 > 1000:
... raise StopIteration()
... return self.a
...
>>> for i in Fib():
... print(i)
...
1
1
2
3
5
8
13
21
34
55
89
144
233
377
610
987
__getitem__
尝试把Fib当做list使用,比如取第三个元素:
>>> Fib()[3]
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'Fib' object does not support indexing
不行!
要表现的像list那样按照按照角标去除元素,需要实现__getiten__():
>>> class Fib(object):
... def __getitem__(self,n):
... a,b = 1,1
... for i in range(n):
... a,b = b,a+b
... return a
...
>>> f = Fib()
>>> f[3]
3
>>> f[10]
89
再来试试Fib如何使用切片方法:
>>> class Fib(object):
... def __getitem__(self,n):
... if isinstance(n,int):
... a,b = 1,1
... for i in range(n):
... a,b = b,a+b
... return a
... if isinstance(n,slice):
... start = n.start
... stop = n.stop
... if start is None:
... start = 0
... a,b = 1,1
... L = []
... for i in range(stop):
... if i >= start:
... L.append(a)
... a,b = b,a+b
... return L
...
>>> f = Fib()
>>> f[0:3]
[1, 1, 2]
>>> f[:5]
[1, 1, 2, 3, 5]
>>> f[:6:2]
[1, 1, 2, 3, 5, 8]
但是,我们还没对负数做处理。要实现一个__getitem__()还有、还可以做很多事情。比如,如果把类看做是一个dict,可以使__getitem__()的参数为key的object。与之对应的是__setitem__()方法,可以把对象视作list或者dict来赋值;此外,还存在__delitem__()方法,用来删除某个元素。
通过上面的方法,我们可以自定义一个类,使其表现的像python自带的list、tuple、dict一样。由此,我们对于‘鸭子类型’的设计有了更深刻的理解。
__getattr__
当我们定义好一个类后,如果想调用类不存在的属性或者方法,我们可以给实例增加一个属性或者方法;其实,python还有另外一个机制,那就是写一个__getattr__()函数,动态返回一个属性。:
>>> class Student(object):
... def __init__(self):
... self.name = 'wc'
... def __getattr__(self,attr):
... if attr == 'score':
... return 88
...
>>> s = Student()
>>> s.name
'wc'
>>> s.score
88
当调用不存在的属性时,python的机制会调用__getattr__()方法来尝试的得到属性。同样的,也适用于返回函数:
>>> class Student(object):
... def __getattr__(self,attr):
... if attr == 'age':
... return lambda:20
...
>>> s = Student()
>>> s.age()
20
注意:只有在没有找到属性的情况下,才会调用__getdattr__()!
继续优化一下:当我们任意调用不存在的属性时,返回指定的错误:
>>> class Student(object):
... def __getattr__(self,attr):
... if attr == 'age':
... return lambda:20
... raise AttributeError('\'Student\' object has no attribute \'%s\'' % attr)
...
>>> s = Student()
>>> s.haha
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 5, in __getattr__
AttributeError: 'Student' object has no attribute 'haha'
这实际上把一个类的所有属性和方法调用全部动态化处理了。相当有用。
__call__
一个对象实例可以有自己的属性和方法。我们能不能直接在实例本身上调用呢?既然这么问,那答案是肯定的。任何类只要定义一个__call__()方法,就可以直接对实例进行调用:
>>> class Student(object):
... def __init__(self,name):
... self.name = name
... def __call__(self):
... print('你好:%s'% self.name)
...
>>> s = Student('wc')
>>> s()
你好:wc
对实例对象进行直接调用就好比对一个函数调用一样,既可以把对象看成函数,把函数看成对象。
如果你把对象看成函数,那么函数本身也可以在运行期间动态创建出来,因为类的实例都是在运行期间创建出来的。
那么怎么判断一个变量是对象还是函数呢?其实更多的时候,我们需要判断一个对象是否能被调用,能被调用的对象就是一个Callable对象:
>>> callable(Student('wc'))
True
>>> callable(max)
True
>>> callable(abs)
True
>>> callable(s)
True
>>> callable(None)
False
>>> callable('str')
False
>>> callable([1,2,3])
更多的内置函数对象参见官网
Python面向对象-定制方法的更多相关文章
- Python 面向对象 特殊方法(魔法方法)
Python 的特殊方法,两边带双下划线的方法. 比如:__init__(self, ...).__del__(self) 1.__init__(self,...) : 构造方法 __init__(s ...
- python面向对象魔术方法补充
一.描述符 在 面向对象 编程中 定义一个(没有定义方法)类:class person , 在这个类里面,有name,age, heigth, weight,等等属性, 这个类就可以看作一个对 per ...
- Python面向对象之方法
普通方法要执行类里面的方法是通过对象触发的 触发的时候把自己赋值给self 类方法 vim day7-7.py #!/usr/bin/python # -*- coding:utf-8 -*- cla ...
- python 面向对象 析构方法
实例化但从来没有调用他,就浪费了,就应该自动删除它 这个实例一直存在内存里 python有个垃圾自动回收机制 , 每段时间会自动刷新整个内存,把内存垃圾东西删除 析构函数: 在实例释放.销毁的时候 ...
- python面向对象-1方法、构造函数
类是指:描述一种事物的定义,是个抽象的概念 实例指:该种事物的一个具体的个体,是具体的东西 打个比方: “人”是一个类.“张三”是人类的一个具体例子 在编程时也是同样的道理,你先自己定义一个“类”,当 ...
- [Python]python面向对象 __new__方法及单例设计
__new__ 方法 使用 类名() 创建对象时,Python 的解释器 首先 会 调用 __new__ 方法为对象 分配空间 __new__ 是一个 由 object 基类提供的 内置的静态方法,主 ...
- Python面向对象 | 鸭子方法
鸭子类型 如果看起来像.叫声像而且走起路来像鸭子,那么它就是鸭子’.python程序员通常根据这种行为来编写程序.例如,如果想编写现有对象的自定义版本,可以继承该对象,也可以创建一个外观和行为像,但与 ...
- 用python面向对象的方法实现欧拉算法和龙格库塔算法
#!/bin/python3 # -*-coding:utf-8 -*- import math import numpy as np #定义一个欧拉算法的类,从而实现不同步长的引用 class Eu ...
- python面向对象--item方法
class Foo: def __getitem__(self, item): print("getitem") return self.__dict__[item] def __ ...
随机推荐
- vue 中 keep-alive 缓存数据、离开时位置
路由中: 页面中: 需要缓存的组件中: 因为是keep-alive 所以在初始化页面的时候 会走一次生命周期 当二次进入的时候就已经是缓存状态了 不会在走生命周期 于是它就有了自己的周期函数分别是 ...
- linux计算机网络基础
OSI7层协议和TCP/IP4层网络协议 第一层:物理层,定义各种物理设备的规范,如通信距离,接口大小等. 第二层:数据链路层,基于mac地址通信是,数据报文封装和相应方式. 第三层:网络层,基于IP ...
- LESSON 3- Discrete Memory-less Sources
1. Entropy H[X] - bounds on Lmin 2. Huffman’s algorithm for optimal source code
- createTextNode
createTextNode()方法将创建一个包含给定文本的新文本文档节点.这个方法的返回值是一个指向新建文本节点的引用指针: reference = document.createTextNode( ...
- Docker 自建私有Registry 私有仓库
目录 说明 介绍 原理 搭建 查看配置文件 启动 上传和下载镜像测试 测试上传镜像 测试下载镜像 说明 记录搭建 docker 私有仓库步骤 介绍 docker镜像可以托管到dockerhub中,跟代 ...
- python_MySQL数据库
MySQL数据库的特点: 1.是关系型数据库 关系型数据库的特点 1.数据是以行和列的的形式存储的 2.这一系列的行和列称为表 ...
- c++关于multiset的头文件包含问题
最近在Bilibili上看到不少侯捷老师C++的视频教程,侯捷老师翻译了很多C++的经典书籍,比如<Essential C++中文版>.<STL源码剖析>,也写了<深入浅 ...
- 转:Spring Boot启动过程
之前在排查一个线上问题时,不得不仔细跑了很多遍Spring Boot的代码,于是整理一下,我用的是1.4.3.RELEASE. 首先,普通的入口,这没什么好说的,我就随便贴贴代码了: SpringAp ...
- php mysql_connect 在同一host下多数据库mysql_select_db()的bug .
操作方法 创建两个数据库test1 test2 同一个host下面 分别在两个数据库中创建表 -- ---------------------------- -- Table structure fo ...
- openlayers5-webpack 入门开发系列结合 echarts4 实现散点图(附源码下载)
前言 openlayers5-webpack 入门开发系列环境知识点了解: node 安装包下载webpack 打包管理工具需要依赖 node 环境,所以 node 安装包必须安装,上面链接是官网下载 ...