我是靠谱客的博主 懵懂苗条,最近开发中收集的这篇文章主要介绍python进阶学习笔记-抽象基类和可散列什么是抽象基类可散列,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

什么是抽象基类

有时候某些类型都有一些共同的特征,它们可以被抽象出来形成一个基类(基类又叫作父类),但这个基类本身不能实例化,只能由子类继承并实现其中的抽象方法后实例化子类对象,这样的类叫抽象基类。也就是说我们创建一个类的时候,里面要包含我们所有要用的方法,不然会报错。因为你一旦创建了实例,这个实例只能调用类中的方法,而不能调用类外面的方法了,而且我们在调用某个类的时候,这个类一定要继承相应的父类,不然也是没有用的。

python中提供了内置模块abc(abstract base class)来模拟实现抽象类。可以通过abc将基类声明为抽象类的方式,然后注册具体类作为这个基类的实现。

python崇尚鸭子类型,鸭子类型(英语:duck typing)是动态类型的一种风格。在这种风格中,一个对象有效的语义,不是由继承自特定的类或实现特定的接口,而是由当前方法和属性的集合决定。在解释性语言中,在定义函数的参数时是无法指定具体参数类型的,另一方面,参数的类型是在解释执行时才能确定。
鸭子类型通常得益于不测试方法和函数中参数的类型,而是依赖文档、清晰的代码和测试来确保正确使用。对象的类型不再由继承等方式决定,而由实际运行时所表现出的具体行为来决定。

抽象基类的作用:定义一些共同事物的规则和行为。(其实这和普通的类的作用没什么区别,但是这个类是必须由子类继承才能够使用,类似于JAVA中的接口。)
那么抽象基类这样实现的目的是什么呢? 假设我们在写一个关于动物的代码。涉及到的动物有鸟,狗,牛。首先鸟,狗,牛都是属于动物的。既然是动物那么肯定需要吃饭,发出声音。但是具体到鸟,狗,牛来说吃饭和声音肯定是不同的,需要具体去实现鸟,狗,牛吃饭和声音的代码。

抽象基类在python并非在于用来继承,主要用来理解python继承的定义,应该尽量使用鸭子类型。抽象基类常会用来作为父类、检验实例类型(结合isinstance判断)和抛出异常说明。

静态类型和动态类型

在上面的赘述中还涉及到了静态类型和动态类型,那么这两者是什么?又有什么区别呢?

静态语言(强类型语言)
静态语言是在编译时变量的数据类型即可确定的语言,多数静态类型语言要求在使用变量之前必须声明数据类型。
例如:C++、Java、Delphi、C#等。

强类型定义语言:强制数据类型定义的语言。一旦一个变量被指定了某个数据类型,如果不经过强制转换,那么它就永远是这个数据类型了。举个例子:如果你定义了一个整型变量a,那么程序根本不可能将a当作字符串类型处理。强类型定义语言是类型安全的语言。

动态语言(弱类型语言)
动态语言是在运行时确定数据类型的语言。变量使用之前不需要类型声明,通常变量的类型是被赋值的那个值的类型。
例如PHP/ASP/Ruby/Python/Perl/ABAP/SQL/JavaScript/Unix Shell等等。

弱类型定义语言
数据类型可以被忽略的语言。它与强类型定义语言相反, 一个变量可以赋不同数据类型的值。强类型定义语言在速度上可能略逊色于弱类型定义语言,但是强类型定义语言带来的严谨性能够有效的避免许多错误。

两者区别
特性
强类型语言是一旦变量的类型被确定,就不能转化的语言。
弱类型语言则反之,一个变量的类型是由其应用上下文确定的。

优势
静态语言
由于类型的强制声明,使得IDE有很强的代码感知能力,故,在实现复杂的业务逻辑、开发大型商业系统、以及那些生命周期很长的应用中,依托IDE对系统的开发很有保障;由于静态语言相对比较封闭,使得第三方开发包对代码的侵害性可以降到最低。

动态语言
思维不受束缚,可以任意发挥,把更多的精力放在产品本身上;
集中思考业务逻辑实现,思考过程即实现过程;

可散列

标准库里的所有映射类型都是利用 dict 来实现的,因此它们有个共同的限制,即只有可散列的数据类型才能用作这些映射里的键(只有键有这个要求,值并不需要是可散列的数据类型)。

原子不可变数据类型(str、bytes 和数值类型)都是可散列类型,frozenset 也是可散列的,因为根据其定义,frozenset 里只能容纳可散列类型。元组的话,只有当一个元组包含的所有元素都是可散列类型的情况下,它才是可散列的。

如果一个对象是可散列的,那么这个对象:

  1. 支持 hash() 函数,并且通过 hash() 方法所得到的散列值是不变的。
  2. 支持通过 eq() 方法来检测相等性。
  3. 若 a == b 为真,则 hash(a) == hash(b) 也为真。

eg:

>>> tt = (1, 2, (30, 40))
>>> hash(tt)
8027212646858338501
>>> tl = (1, 2, [30, 40])
>>> hash(tl)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'
>>> tf = (1, 2, frozenset([30, 40]))
>>> hash(tf)
-4118419923444501110

一般来讲用户自定义的类型的对象都是可散列的,散列值就是它们的 id() 函数的返回值,所以所有这些对象在比较的时候都是不相等的。如果一个对象实现了 __eq__方法,并且在方法中用到了这个对象的内部状态的话,那么只有当所有这些内部状态都是不可变的情况下,这个对象才是可散列的。

根据这些定义,字典提供了多种创建字典的不同方式:

>>> a = dict(one=1, two=2, three=3)
>>> b = {'one': 1, 'two': 2, 'three': 3}
>>> c = dict(zip(['one', 'two', 'three'], [1, 2, 3]))
>>> d = dict([('two', 2), ('one', 1), ('three', 3)])
>>> e = dict({'three': 3, 'one': 1, 'two': 2})
>>> a == b == c == d == e
True

这次的分享就到这里啦,有什么问题请大家指出,我一定会及时的修改!

最后

以上就是懵懂苗条为你收集整理的python进阶学习笔记-抽象基类和可散列什么是抽象基类可散列的全部内容,希望文章能够帮你解决python进阶学习笔记-抽象基类和可散列什么是抽象基类可散列所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(56)

评论列表共有 0 条评论

立即
投稿
返回
顶部