返回顶部
首页 > 资讯 > 后端开发 > Python >Python编程:接口
  • 311
分享到

Python编程:接口

python 2023-10-27 12:10:25 311人浏览 安东尼

Python 官方文档:入门教程 => 点击学习

摘要

1.Python文化中的接口和协议         在python中,我们把协议定义为非正式的接口,是让Python这种动态类型语言实现多态的方式。那么,接口在动态类型语言中是怎么运作的呢?         首先,基本的事实是,Python

1.Python文化中的接口和协议

        在python中,我们把协议定义为非正式的接口,是让Python这种动态类型语言实现多态的方式。那么,接口在动态类型语言中是怎么运作的呢?

        首先,基本的事实是,Python语言没有interface关键字,而且,除了抽象基类,每个类都有接口:类实现和继承的公开属性,包括特殊方法,如:_getitem_和_add_。按照定义,受保护的属性和私有属性不在接口中:即便是受保护的属性,也只能采用命名约定实现,私有属性可以轻松访问。

        其次,不要觉得把公开数据属性放入对象的接口中不妥,因为如果需要总能实现读值方法和设值方法,把数据属性变成特性,使用obj.attr句法的客户代码不受到影响。

class Vector2d:    typecode = 'd'        def __init__(self, x, y):        self.x = float(x)        self.y = float(y)            def __iter__(self):        return  (i for i in (self.x, self.y))    class Vector2d:    typecode = 'd'    def __init__(self, x, y):        self.x = float(x)        self.y = float(y)    @property    def x(self):        return self._x        @property    def y(self):        return self._y        def __iter__(self):        return (i for i in (self.x, self.y))

        上面的代码中,第一段中x、y是公开的数据,而第二段x、y是使用特性实现的,将其变成了只读特性。这段代码是我们之前实现过的。

        其实关于接口,这里还有一个补充的实用定义:对象公开方法的子集,让对象在系统中扮演特定的角色。也就是说,接口是实现特定角色的方法集合。像Python文档中所说的文件类对象和可迭代对象就是这个意思。另外,协议与继承也没有关系,一个类可能会实现多个接口,从而让实例扮演多个角色。

        协议是接口,但不是正式的,因此协议不能像正式接口那样施加限制,一个类可能只实现部分接口,这是允许的。

2.Python喜欢序列

        Python数据模型的哲学是尽量支持基本协议。对于序列来说,即便是最简单的实现,Python也会力求做到最好。

class Foo:    def __getitem__(self, pos):        return range(0, 30, 10)[pos]f = Foo()print(f[0])print(20 in f)print(15 in f)

        在上面的实例中,定义了Foo类,它并没有继承abc.Sequence,而是只实现了序列协议的一个基本方法。通过运行代码可以发现,虽然没有_iter_方法,Foo实例也是可迭代的对象,因为存在_getitem_方法,Python会调用它,传入从零开始的整数索引,尝试迭代对象(当然,这是一种后备机制,之前讲过)。尽管没有实现_contains_方法,但是Python足够智能,等迭代Foo实例,也能运行in运算符。这一切都指向了协议的重要性。

3.是用猴子补丁在运行时实现协议

        我们之前定义过FrenchDeck类有个重大的缺陷,就是无法进行洗牌。我们不能直接使用random.shuffle来进行洗牌,因为我们定义的FrenchDeck类是不可变的序列协议,要将其变成可变的需要提供_setitem_方法。

from random import shuffledef set_card(deck, poisition, card):    deck._card[poisition] = cardFrenchDeck.__setitem__ = set_card()shuffle(deck)

        在这个实例中,我们将定义的函数赋值给FrenchDeck类的_setitem_属性,然后就可以用shuffle来进行卡牌的打乱了。

        这个实例的关键是,set_card函数要知道deck对象有一个名为_cards的属性,而且它还是可变序列。然后,我们把set_card函数赋值给_setitem_这个特殊方法,从而将这个方法依附到FrenchDeck类上。这种技术叫猴子补丁:在运行时修改类和模块,而不改动源代码。但是,打补丁的代码要与打补丁的程序十分耦合,而且要处理好隐藏和没有文档的部分。

4.定义抽象基类的子类

        在Python中,我们一般是先利用现有的抽象基类,然后在斗胆自己定义。下面我们将French

Deck2声明为collections.MutableMapping的子类。

import collectionsCard = collections.namedtuple('Card', ['rank', 'suit'])class FrenchDeck2(collections.MutableMapping):    ranks = [str(n) for n in range(2, 11)] + list('JQKA')    suits = 'spades diamonds clubs hearts'.split()    def __init__(self):        self._cards = [Card(rank, suit) for suit in self.suits for rank in self.ranks]    def __len__(self):        return len(self._cards)    def __getitem__(self, poIstion):        return self._cards[poistion]    def __setitem__(self, poistion, value):        self._cards[poistion] = value    def __delitem__(self, poistion):        del self._cards[poistion]    def insert(self, poistion, value):        self._cards.insert(poistion, value)

        为了支持洗牌,我们只需要实现_setitem_方法,同时因为是继承collections.MutableMapping类,就必须实现_delitem_方法,并且还要实现_insert_方法。

        通常,导入时,Python不会检查抽象方法的实现,在运行实例化时才会真正的检查。当检查到没有正确实现某个抽象方法时,就会抛TypeError异常。这也就是我们要定义insert等方法的原因。另外,要想实现子类,我们可以覆盖从抽象基类中继承的方法,以更高效的方式重新实现。

5.标准库中的抽象基类

        Python标准库提供了一些抽象基类。大多数抽象基类在collections.abc模块中定义,不过其它地方也会有一些。如:numbers和io包。但是总的来说,collections.abc中抽象基类最常用。

5.1collections.abc模块中的抽象基类

        在collections.abc模块中定义了16个抽象基类,简要的UML类图,如下图所示。

(1)Iterable、Container和Sized

        各个集合应该继承这三个抽象基类,或者至少实现兼容的协议。Iterable通过_iter_方法支持迭代、Container通过_contains_方法支持in运算符、Sized通过_len_方法支持len()函数。

(2)Sequence、Mappling和Set

        这三个是主要的不可变集合类型,而且各自都有可变的子类。

(3)MappingView

        在python3中,映射方法.items()、.keys()和.values()返回的对象是ItemsView、KeysView、ValuesView的实例。前两个类还从Set类继承了丰富的接口。

(4)Callable和Hashable

        这两个抽象基类与集合没有太大关系,只不过是因为它们重要,才把它们放到该模块中。这两个抽象基类的作用是为内置函数isinstance提供支持,以一种安全的方式判断对象能不能调用或者散列。

(5)Iterator

        它是Iterable的子类,后续我们会讲到。

5.2抽象基类的数字塔

        numbers包定义的是数字塔(即各个抽象基类的层次结构是线性的)。其排序顺序如下。

Number位于顶端的超类
Complex
Real可以检查一个数是否是浮点数
Rational
Intergral可以用来检查一个数是否是整数

6.定义并使用一个抽象基类

        为了证明有必要定义抽象基类,我们先要在框架中找到使用它的场景。想象一下下面这个场景:你要在网站和移动应用中随机显示广告,但是要在整个广告清单轮转一遍之前,不重复显示广告。假设我们构建一个广告管理框架,名为ADAM。它的职责之一是,支持用户提供随机挑选的无重复类。下面,我们将定义一个Tombola的类来实现这个功能。

import abcclass Tombola(abc.ABC):    @abc.abstractmethod    def load(self, iterable):        """从可迭代对象中添加元素"""    @abc.abstractmethod    def pick(self):        """随机删除元素,然后将其返回。如果实例为空,这个方法应该抛出LookupError"""    def loaded(self):        """如果至少有一个元素,就返回Ture"""        return bool(self.inspect())    def inspect(self):        """返回有序元组,由当前元素构成"""        items = []        while True:            try:                items.append(self.pick())            except LookupError:                break        self.load(items)        return tuple(sorted(items))

        自己定义的抽象基类要继承abc.ABC类。抽象方法使用@abstractmethod装饰器来标记,而且定义体中通常只有文档字符串,不定义具体的方法,但是,在有的情况下也需要定义具体方法,这时,抽象基类中的具体方法只能依赖抽象基类定义的接口(即只能使用抽象基类中的其它具体方法、抽象方法或特性)。根据文档字符串,如果没有元素可选,应该抛出LookupError。当我们不知道具体子类如何存储元素时,我们可以不断调用pick()方法,吧Tombola清空,再使用load()把所有元素都加进去。

6.1抽象基类句法详解

        声明抽象基类最简单的方法是继承abc.ABC或者其他抽象基类。但是,如果你使用的是旧版本的Python,并且继承现有的抽象基类不可取时,必须在class语句中使用metaclass=关键字。如下:

class Tombola(metaclass=abc.ABCmeta):

6.2定义Tombola抽象基类的子类

        定义好Tombola抽象基类后,我们会开发两个具体的子类,满足Tombola具体的接口。首先,我们先定义一个名为binGocage的具体子类。

import randomfrom tombola import Tombolaclass BingoCage(Tombola):    def __init__(self, items):        self._randomizer = random.SystemRandom()        self._items = []        self.load(items)    def load(self, items):        self._items.extend(items)        self._randomizer.shuffle(self._items)    def pick(self):        try:            return self._items.pop()        except IndexError:            raise LookupError('pick from empty BingoCage')    def __call__(self):        self.pick()

        在该段代码中,我们首先指定其为Tombola的子类,假设我们将在线上游戏使用这个。我们先使用random模块来进行随机,再使用load()方法来进行初始加载。该类会从Tombola类中继承loaded和inspect方法,当然,我们也可以进行覆盖,使用个人能够高效的代码。

        其次,我们定义一个LotteryBlower类。

import randomfrom tombola import Tombolaclass LotteryBlower(Tombola):    def __init__(self, iterable):        self._balls = list(iterable)    def load(self, iterable):        self._balls.extend(iterable)    def pick(self):        try:            poistion = random.randrange(len(self._balls))        except ValueError:            raise LookupError('pick from empty LotteryBlower')        return self._balls.pop(poistion)    def loaded(self):        return bool(self._balls)    def inspect(self):        return tuple(sorted(self._balls))

        同样,LotteryBlower类也是为Tombola的子类。该类首先初始化方法接收任何可迭代的对象:把参数构建成列表。随后,在pick方法中检查,如果范围为空,函数会抛出ValueError,当然,我们为了兼容,抛出LookupError。如果范围不为空,就从其中随机弹出元素。最后,通过重新定义loaded和inspect方法,覆盖了原有的代码。

6.3Tombola的虚拟子类

        “白鹅”类型的一个基本特性:即便不继承,也有办法把一个类注册为抽象基类的虚拟子类。这样做时,我们保证注册的类忠实地实现了抽象基类定义的接口,而Python也会相信我们。一旦我们说谎了,就会抛出异常。

        注册虚拟子类的方法是在抽象基类上调用reGISter方法。这样做之后,注册的类就会变成抽象基类的虚拟子类,而且issubclass和isinstance等函数都能识别。但是,注册的类不会从抽象基类中继承任何属性和方法。

        register方法通常作为普通函数来进行使用,但有时也作为装饰器进行使用。如下:

from random import randrangefrom tombola import Tombola@Tombola.registerclass Tombolist(list):    def pick(self):        if self:            poistion = randrange(len(self))            return self.pick(poistion)        else:            raise LookupError('pop from empty TomboList')    load = list.extend    def loaded(self):        return bool(self)    def inspect(self):        return tuple(sorted(self))

         我们先是把Tombolist注册为Tombola的虚拟子类,又将Tombolist拓展为list,因此,用它继承list类中的方法,可以调用pop等方法。pick方法调用继承自list的pop方法,传入一个随机元素的索引。                                                                                                                                                    7.Tombola子类的测试方法                                                                                                                

        我们编写的测试实例中有两个类的属性,用它们内省类的继承关系。

(1)_subclasses_

        这个方法返回类的直接子类列表,不含虚拟子类。

(2)_abc_registry_

        只有抽象基类有这个数据属性,其值是一个WeakSet对象,即抽象类注册的虚拟子类的弱引用。                                                                                                                                                                                                                                                                                                                                                                                                                                                                          

来源地址:https://blog.csdn.net/weixin_56051592/article/details/128441632

--结束END--

本文标题: Python编程:接口

本文链接: https://lsjlt.com/news/490602.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Python编程:接口
    1.Python文化中的接口和协议         在Python中,我们把协议定义为非正式的接口,是让Python这种动态类型语言实现多态的方式。那么,接口在动态类型语言中是怎么运作的呢?         首先,基本的事实是,Python...
    99+
    2023-10-27
    python
  • Python中面向接口编程详情
    目录前言概述 Python 接口非正式接口前言 接口在软件工程扮演重要角色,随着应用程序的功能不断扩展,代码库的更新和改变也难以管理。在许多情况下,会发现有一些看起来非常相似,但却不...
    99+
    2024-04-02
  • python编写登录接口
    要求: 输入用户名密码       认证成功显示欢迎信息    输错三次以后锁定 代码如下: # Author:YKwhile(True): select=input('请问是注册还是登录') if select == '注册...
    99+
    2023-01-30
    接口 python
  • Java编程接口详细
    目录一、抽象类和抽象方法二、接口三、Java中的多重继承四、通过继承来扩展接口1、组合接口时的名字冲突五、适配接口六、接口中的域七、嵌套接口1.类中的接口2.接口中的接口八、接口与工...
    99+
    2024-04-02
  • Python中怎么实现面向接口编程
    本篇文章为大家展示了Python中怎么实现面向接口编程,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。”面向接口编程“写 Java 的朋友耳朵已经可以听出干茧了吧,当然这个思想在 Java  ...
    99+
    2023-06-15
  • Python中面向接口编程实例分析
    这篇文章主要讲解了“Python中面向接口编程实例分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Python中面向接口编程实例分析”吧!前言接口在软件工程扮演重要角色,随着应用程序的功能...
    99+
    2023-06-30
  • Python数据库编程接口怎么使用
    今天小编给大家分享一下Python数据库编程接口怎么使用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。一、前言在项目开发中,...
    99+
    2023-07-02
  • Unix Shell 与 Python:接口编程的新思路?
    Unix Shell 作为操作系统的命令行界面,一直以来都是程序员们不可或缺的工具。而 Python 作为一门流行的编程语言,也受到了广泛的青睐。那么,将这两者结合起来,会带来什么样的新思路呢? Unix Shell 和 Python 的...
    99+
    2023-10-20
    unix 接口 shell
  • python编写登录接口(上)
    中途经过了好几天都没有动手了,得坚持下去啊刚看了Alex老师的视频,其中有个题目如下:编写登录接口-输入用户密码-认证成功后显示欢迎信息-输错三次后锁定# -*- coding: cp936 -*-#用户名保存在一个文件名为user.txt...
    99+
    2023-01-31
    接口 python
  • python怎么编写api接口
    在Python中编写API接口需要使用Web框架来处理HTTP请求和响应。以下是使用Flask框架编写API接口的示例:```pyt...
    99+
    2023-08-25
    python
  • Python 编程算法:如何实现实时接口?
    在计算机科学中,接口是指两个软件系统之间的通信方式。实时接口是指在实时应用程序中使用的接口。Python 是一种高级编程语言,具有许多用于编写实时应用程序的算法。在这篇文章中,我们将探讨如何使用 Python 编写实时接口。 实时接口的...
    99+
    2023-10-02
    编程算法 接口 实时
  • 如何在Python中优化并发编程接口?
    在当今的计算机领域中,处理大量数据和任务的需求越来越高。为了提高程序的效率,我们需要使用并发编程来实现任务的并行处理。在Python中,有多种方式来实现并发编程,如多线程、多进程和协程。然而,这些方式在实现上都有一定的限制和缺陷,因此需要优...
    99+
    2023-05-26
  • python编写的多线程接口并发测试
    import requests import json import threading import time import uuid class postrequests(): def __init__(self): ...
    99+
    2023-01-31
    多线程 接口 测试
  • python练习_编写登陆接口
    具体需求 输入用户名密码 认证成功后显示欢迎信息 输错三次后锁定 一、 实现思路                                                                             ...
    99+
    2023-01-30
    接口 python
  • 编写python调用dubbo接口hes
    引子今天有小伙伴问到了怎么用python调用dubbo的接口的方法,就随便写了这么一篇文章。其实dubbo接口可以使用loadrunner、jmeter等完成,最好是熟悉java语言的,那么编写起来就丝滑了很多哦那么用python来调用其实...
    99+
    2023-01-31
    接口 python dubbo
  • 接口编程:PHP异步编程的新趋势?
    随着互联网的不断发展,对于Web应用程序的响应速度和性能要求越来越高,而PHP作为Web开发中最流行的语言之一,也在不断的发展和完善。在这个过程中,异步编程逐渐成为PHP开发中的一个新趋势。本文将介绍什么是异步编程,为什么需要异步编程,以...
    99+
    2023-09-26
    异步编程 leetcode 接口
  • PHP面向对象编程:面向接口编程
    dip 是一种设计模式,通过创建依赖于接口而非具体实现的类来实现松耦合和易维护。好处包括灵活性、可测试性和可扩展性。要实现 dip,请定义接口、创建实现接口的类,并将接口作为依赖项传递给...
    99+
    2024-05-10
    php 面向对象 php面向对象编程
  • Python操作数据库之数据库编程接口
    目录一、前言二、连接对象1.获取连接对象2.连接对象的方法三、游标对象一、前言 在项目开发中,数据库应用必不可少。虽然数据库的种类有很多,如SQLite、MySQL、Oracle等,...
    99+
    2024-04-02
  • 如何利用 Python IDE 接口提升编程效率?
    如何利用 Python IDE 接口提升编程效率? Python 是一种广泛应用的编程语言,因其简单易学、可扩展性强、拥有强大的库支持等特点而备受开发者的欢迎。而 Python 的 IDE(集成开发环境)也是开发者必不可少的工具之一。Pyt...
    99+
    2023-08-03
    面试 ide 接口
  • Python串口编程(转载)
    python的串口网上有很多例子,这里了只是把认为好的整理到一起。 首先,应该安装serial模块,还能开始后续的操作。我用的python2.6,serial模块可以在这里下载安装serial模块下载 1,字符串的发送接收 短接串口的...
    99+
    2023-01-31
    串口 Python
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作