我的编程空间,编程开发者的网络收藏夹
学习永远不晚

Python的对象协议

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

Python的对象协议

    Python是一门动态语言,Duck Typing概念遍布其中,所以其中的Concept并不是以类型的约束为载体,而是使用称作为协议的概念。那什么是Duck Typing呢?

    Duck Typing是鸭子类型,在动态语言中用的较多,是动态类型语言设计的一种风格。在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口决定,而是由当前方法和属性的集合决定。说白了就是并不关心对象是什么类型,只关心行为。

    

    这个概念的名字来源于由James Whitcomb Riley提出的鸭子测试,“鸭子测试”可以这样表述:

    “当看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。”

 在鸭子类型中,关注的不是对象的类型本身,而是它是如何使用的。

看下面例子:

#coding=utf-8
class Duck:
    def quack(self):
        print u"嘎嘎嘎!"
    def feathers(self):
        print u"这是一只Duck。"

class Person:
    def quack(self):
        print u"hello,world!"
    def feathers(self):
        print u"这是人。"

def in_the_forest(duck):
    duck.quack()
    duck.feathers()

def game():
    donald = Duck()
    john = Person()
    in_the_forest(donald)
    in_the_forest(john)

game()

运行结果不用贴出来,都知道是什么。那么上面代码从何体现出Duck Typing风格呢?

    看看in_the_forest()函数,它对它的参数只有两个要求,那就是这个参数必须要有quack()和feathers()两个方法,不管它是什么类型,只要有这两个方法,都可以作为in_the_forest()函数的参数,而类Duck和Person都实现了这个方法,所以它们的实例都可以作为in_the_forest()的参数。这个就是鸭子类型,不关注对象类型本身,只关心行为。这一点更C++还是有很大区别的,我也学习过C++,也了解C++多态性以及虚函数所以感觉这差别还是蛮大的。

    现在来看看什么是协议吧,简单的说,在python中我需要调用你的某个方法,你正好有这个方法,这就是协议,比如在加法运算中,当出现加号(+)时,那么按照数值类型相关的协议,python会自动去调用相应对象的__add__()方法,这就是协议。

python中有很多协议,比如下面代码:

#coding=utf-8
a = 1
print dir(a)

结果如下:

['__abs__', '__add__', '__and__', '__class__', '__cmp__', '__coerce__', '__delattr__', '__div__', '__divmod__', '__doc__', '__float__', '__floordiv__', '__format__', '__getattribute__', '__getnewargs__', '__hash__', '__hex__', '__index__', '__init__', '__int__', '__invert__', '__long__', '__lshift__', '__mod__', '__mul__', '__neg__', '__new__', '__nonzero__', '__oct__', '__or__', '__pos__', '__pow__', '__radd__', '__rand__', '__rdiv__', '__rdivmod__', '__reduce__', '__reduce_ex__', '__repr__', '__rfloordiv__', '__rlshift__', '__rmod__', '__rmul__', '__ror__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__', '__rtruediv__', '__rxor__', '__setattr__', '__sizeof__', '__str__', '__sub__', '__subclasshook__', '__truediv__', '__trunc__', '__xor__', 'bit_length', 'conjugate', 'denominator', 'imag', 'numerator', 'real']

上面代码中,a是整数对象,我们列出来该对象的所有属性,上面的属性列表中,以"__"开头并且以"__"结尾的基本上都是对象协议依赖的方法。是不是很多呀,我们可以将它们分成以下几类:

(1)类型转换协议

    类型转换协议,顾名思义就是用来进行类型转的咯,比如a=1,a是整型,想把它变成float浮点型,我们可以这样:

#coding=utf-8
a = 1
print type(a)
b = a.__float__()
print b
print type(b)

wKioL1fzqnzwH3kxAAAb5xZ86lE377.png-wh_50

当然你也可以用内置函数float()。

除了__float__()外,还有__str__()、__repr__()、__int__()、__long__()、__nonzero__()等等,这些都是类型转换协议依赖的方法。

在这里提下__nonzero__(),他用t于将类转换为布尔值。通常在用类进行判断和将类转换成布尔值时调用。通常会在if等条件语句会调用该方法。比如:

#coding=utf-8
list1 = []
if list1:
    print "1"

上面代码在执行过程中,先会调用list1对象的__nonzero__()方法,判读它是不是空,是的话就会转换为False。假设有些对类没有定义__nonzero__()方法,那么将如何判断真假呢?此时对象会获取__len__()方法,如果该方法返回值为0,则表示为假。

如果一个类即没有定义__nonzero__()方法,也没有定义__len__()方法,那么该类的所有实例用if判断的话全为真。

比如看下面例子:

#coding=utf-8
class A:
    def __nonzero__(self):
        print u"定义了__nonzero__()方法"
        return 1

class B:
    def __len__(self):
        print u"没定义__nonzero__()方法,但定义了__len__()方法"
        return 1

class C:
    pass

if A():
    a = 1
    print a
if B():
    a = 2
    print a
if C():
    a = 3
    print a

运行结果如下:

wKiom1fzsLezUZRqAAAmngDjIDs276.png-wh_50

希望上面的例子能够帮助你理解部分知识。


(2)用以比较大小的协议

这个协议依赖于__cmp__()方法,当两者相等时返回0,self<other时返回负值,反之返回正值。但是这种返回有点复杂,Python又定义了__eq__()、__ne__()、__lt__()、__gt__()等方法来实现相等、不等、小于和大于的判定。这也是Python对==,!=,<,>等操作符进行重载支撑的机制,也就是说重载这些操作符,就是要重新定义对应的方法。


(3)与数值类型相关的协议

这一类方法比较多,主要是数值之间的一些操作。

分类
方法操作符/函数说明







数值运算符

__add__+

__sub__

-
__mul__*
__div__/
__floordiv__//整除
__truediv__/真除法
__pow__**幂运算
__mod__%取余
__divmod__divmod()余、除






位运算符

__lshift__<<向左移位
__rshift__>>向右移位
__and__&
__or__|
__xor__^异或
__invert__~










运算赋值符

__iadd__+=
__isub__-=
__imul__*=
__idiv__/=
__ifloordiv__//=
__itruediv__/=
__ipow__**=
__imod__%=
__ilshift__<<=
__irshift__>>=
__iand__&=
__ior__|=
__ixor__^=


其它

__pos__+
__neg__-
__abs__abs()绝对值

举个例子,比如C++中,"<<"可表示输出流,我们也可以将python中"<<"重载为具有输出流功能。代码如下:

#coding=utf-8
class endl(object):
    pass
class Cout(object):
    def __lshift__(self, other):
        if other is endl:
            print
            return
        print other
        return self
cout = Cout()
cout << "hello" << "world" << endl

运行结果如下:

wKioL1f0stDBrUuSAAAaZUbhgYw364.png-wh_50

不过在python中,将"<<"操作符重载为具有输出流功能,基本上是没有意义,在这里只是举例说明。

另外Python中还有一个特有的概念:反运算。例如a + b,调用的是a的__add__()方法,如果a没有__add__()方法,但b有,可是这种写法调用b.__add__()又不对的,这时候Python有了一个反运算协议,它会去检测b中有没有__radd__(),如果有的话,那么a为参数调用之。类似__radd__()方法,所有数值运算和位运算都之处,规则一律在前面加前缀r。


(4)容器类协议

既然为容器,那么肯定会有查询、取值、删除、赋值、求长度等等一系列动作行为,那么必有对应的方法与这些操作对应。打印出dir(list)的值,结果如下:

['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__setslice__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']

其中:

求长度,也就是查询容器内有多少个对象,用__len__()方法,内置函数len()就是通过该方法实现的。

取值、删除、赋值依次对应__getitem__()、__delitem__()、__setitem__(),有些容器没有__setitem__(),比如字符串,应为字符串是不可变对象

__iter__()实现了迭代协议,__reversed__()则提供了对内置函数reversed()的支持,用来排序。

还有成员关系判定符in和not in,对应的方法是__contains__()


(5)可调用对象协议

可调用对象,也就是类似函数对象,能够让类实例表现的像函数一样,这样可以让每一个函数调用都有所不同。怎么理解这句话呢?还是看例子吧。

#coding=utf-8
class A(object):
    def __init__(self,name):
        self.name = name
    def __call__(self):
        print "dongn something with %s"%(self.name)

a = A('li lei')
b = A('han ×××')
print a()
print b()

运行结果如下:

wKioL1fzxLvz9_mYAAAehdrZUyE354.png-wh_50

看看上面的例子,我们能够像调用函数一样调用实例

对象通过提供__call__(slef, [,*args [,**kwargs]])方法可以模拟函数的行为,如果一个对象x提供了该方法,就可以像函数一样使用它,也就是说x(arg1, arg2...) 等同于调用x.__call__(self, arg1, arg2) 。


(6)哈希协议

如果对象有__hash__()方法,表示是一个可哈希对象。__hash__()方法支持这hash()这个内置函数。按照文档里面的解释“如果一个对象是可哈希的,那么在它的生存期内必须不可变(需要一个哈希函数),而且可以和其他对象比较(需要比较方法).比较值相同的对象一定有相同的哈希值”。

    这也就是说所有不可变的内置类型t都是可哈希的,比如string,tuple。所有可变的内置类型都是不可哈希的,比如list,dict(即没有__hash__()方法)。字典的key必须是可哈希的,所以tuple,string可以做key,而list不能做key。


(7)上下文管理器协议

这个在之前的博文中讲过,在此不做过多解释,可参考之前的相关博文。http://11026142.blog.51cto.com/11016142/1845862


免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

Python的对象协议

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

Python的对象协议

Python是一门动态语言,Duck Typing概念遍布其中,所以其中的Concept并不是以类型的约束为载体,而是使用称作为协议的概念。那什么是Duck Typing呢?    Duck Typing是鸭子类型,在动态语言中用的较多,是
2023-01-31

WebSocket协议与TCP协议的对比与选择

在网络通信中,TCP协议是一种可靠的传输协议,广泛应用于各种网络通信场景。而WebSocket协议则是一种基于HTTP的应用层协议,它提供了双向通信的能力,使得客户端和服务器之间可以实时地进行数据交互。本文将对WebSocket协议和TCP
2023-10-21

PHP phar:协议对象注入技术介绍

前言在之前的BlackHat 2018大会上公布了一款针对PHP应用程序的全新攻击技术。我们将通过这篇文章简单介绍下。来自Secarma的安全研究员Sam Thomas发现了一种新的开发技术,它可以导致PHP对象注入漏洞——而无需使用PHP
2023-06-04

Python中的端口协议之基于UDP协议

UDP协议:  1、python中基于udp协议的客户端与服务端通信简单过程实现  2、udp协议的一些特点(与tcp协议的比较)       3、利用socketserver模块实现udp传输协议的并发通信----------------
2023-01-31

Java Socket如何使用加密协议传输对象

本篇文章为大家展示了Java Socket如何使用加密协议传输对象,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。前面几篇博文提到了Socket中一些常用的用法,但是对于一些有安全要求的应用就需要加密
2023-06-17

Java Socket使用加密协议进行传输对象的方法

本文实例讲述了Java Socket使用加密协议进行传输对象的方法。分享给大家供大家参考,具体如下:前面的几篇文章介绍了Socket中一些常见的用法,但是对于一些有安全要求的应用就需要加密传输的数据,此时就需要用到SSLSocket了。还是
2023-05-31

Python的迭代器协议

迭代器是Python中的一个高级概念,迭代器是一个实现了迭代器协议的对象,那何为迭代器协议呢?满足下面两个条件就行。(1)该对象实现了__iter__()方法;(2)该对象实现了next()方法,返回当前元素,并指向下一个元素的位置,如果当
2023-01-31

HTTP协议(9)Python requ

通过Python中的requests模块也可以来发送HTTP请求,接收HTTP响应,从而实现一些更加灵活的操作。requests是第三方库,不过在Kali中已经自带了该模块。Python3和Python2的用法稍微有些差别,这里先以Pyth
2023-01-31

Python中TCP协议的理解

Test01–>TCP客户端案例#! /usr/bin/env python3# -*- coding:utf-8 -*- from socket import *def main(): # 1.创建socket client_
2023-01-31

TCP协议与UDR协议的分析

  互连网早期的时候,主机间的互连使用的是NCP协议。这种协议本身有很多缺陷,如:不能互连不同的主机,不能互连不同的操作系统,没有纠错功能。为了改善这种缺点,大牛弄出了TCP/IP协议。现在几乎所有的操作系统都实现了TCP/IP协议栈。 首先咱们弄清楚,TCP协议和UCP协议与TCP/IP协议的联系,很多人犯糊涂了,一
TCP协议与UDR协议的分析
2024-04-18

python实现onvif协议-2

from suds.client import Clientfrom suds.wsse import Securityfrom suds_passworddigest.token import UsernameDigestTokenurl
2023-01-31

Python中SSH协议的实现 - Pa

操作系统维护时, 一般会通过ssh命令连接到远端服务器, 进行某些操作. 那Python中如何完成这些呢, 当然也能执行ssh命令, 但还有更优雅的方式, 借助Paramiko, 其为实现了SSHv2协议的一开源项目, 下面主要使用了它的s
2023-01-31

Python Web开发中的WSGI协议

在Python Web开发中,我们一般使用Flask、Django等web框架来开发应用程序,生产环境中将应用部署到Apache、Nginx等web服务器时,还需要uWSGI或者Gunicorn。一个完整的部署应该类似这样:Web Serv
2023-01-31

TCP协议与UDP协议的区别与联系

  网络通讯上网协议是开发网络程序的基础,目前最常用的协议是TCP/IP协议和UDP协议,而其他的如RMI、SOAP、FTP等协议都可以说是构建在这两者之上。  1、面向连接的TCP  “面向连接”就是在正式通信前必须要与对方建立起连接。比如你给别人打电话,必须等线路接通了,对方拿起话筒才能互相
TCP协议与UDP协议的区别与联系
2024-04-18

WebSocket协议与HTTP协议的差异与联系

引言:随着互联网的普及,Web应用的需求不断增加,为了实现实时交互和推送功能,新的通信协议WebSocket应运而生。而传统的HTTP协议也在这个过程中逐渐被WebSocket取代。本文将重点探讨WebSocket协议与HTTP协议的差异与
2023-10-21

距离矢量路由协议与链路状态路由协议之对比

  动态路由协议也是路由协议中很重要的部分,可能很多人还是不了解动态路由协议。说到动态路由协议,不得不说距离矢量与链路状态,因为大多数路由协议都属于两类之一。不了解,没关系,希望看完本文你有些收获,那我开始进入今天的学习吧!  距离矢量与链路状态有着不同的算法,这些算法决定着路由协议以何种方式计算出最优路径,如何得到路
距离矢量路由协议与链路状态路由协议之对比
2024-04-18

mqtt协议和tcp协议的区别有哪些

小编给大家分享一下mqtt协议和tcp协议的区别有哪些,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!区别:1、MQTT诞生于1999年互联网初期,TCP协议诞生于
2023-06-15

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录