Python基础知识学习记录专栏

Python

Python是一种解释型、面向对象、动态数据类型的高级程序设计语言。
由于Python是一种解释型语言,所以开发过程中没有了编译这个环节,Python是交互式语言,可以直接执行python代码,Python支持面向对象的风格或代码封装在对象的编程技术。

Python的内存管理

Python的内存管理主要是从三个方面进行的

  1. 对象的引用计数机制
  2. 垃圾回收机制
  3. 内存池机制

对象的引用计数机制

Python内部使用引用计数,来保持跟踪内存中的对象,所有对象都有引用计数,当一个对象的引用计数为0的时候,这个对象将会被垃圾回收机制进行回收。
引用计数增加的主要场景:

  1. 对象被创建时: a = “ABC”
  2. 引用创建时: b = a
  3. 被当做参数传递给函数的时候:foo(a)
  4. 作为容器对象(list,元组,字典)的一个元素时: lis = [1, a, ‘33’]

引用计数减少的主要场景:

  1. 一个本地引用离开了他的作用域的时候:foo(a)函数结束时,a指向的对象引用减少1
  2. 引用的对象被显示的销毁时: del a
  3. 对象的引用被赋值给其他对象时: a = 7
  4. 对象从一个容器对象(list,元组,字典) 中移除的时候:lis.remove(a)
  5. 容器对象本身被销毁 del lis 或者容器对象本身离开了作用域

python的垃圾回收

垃圾回收是Python和Java等语言进行内存管理的一种方式,用来清除无用的垃圾对象。在C语言以及C++中需要开发人员去手动进行内存的维护,但是在Python和Java中有自动的内存管理机制,不在需要动态的释放内存,这种机制就是垃圾回收。垃圾回收机制还有一个循环垃圾回收器,确保释放循环引用对象(a引用b,b引用a导致其计数永远不为0)

内存池机制

Python提供了对内存的垃圾收集机制,但是Python并不是将不用的内存返回给操作系统,而是将不用的内存放到了内存池中。
对于Python对象,整数、浮点数、List都有独立的私有内存池,对象间不共享他们的内存池。如果分配又释放了大量的整数,用于缓存这些整数的内存就不能再分配给浮点数。

Pymalloc机制

为了加速Python的执行效率,Python引入了一个内存池机制,用于管理小块内存的申请和释放,Python中所有小于256个字节的对象都使用pymalloc实现的分配器。

malloc机制

当需要使用的内存块大于256字节的时候,就会直接使用系统的malloc,每次分配一块大小为256K的大块内存,经由内存池等级的内存的回收还是会回到内存池,并不会调用C的free释放掉,以便下次使用。

Python的匿名函数

lambda表达式通常是在需要一个函数,但是又不想费神去命名一个函数的场合下使用,也就是指匿名函数。 首要用途就是指短小的回调函数。

# 匿名函数的格式
lambda [arguments]:expression
# 例子
# lambda函数的声明
a = lambda x,y:x+y
# lambda函数的使用
a(3,11)

Python的数据类型

Python中有6个标准的数据类型:Number(数字),String(字符串),List(列表),Tuple(元组),Set(集合),Dictionary(字典)
Python中的6个标准的数据类型中又分成了可变数据和不可变数据:
可变数据:List(列表),Dictionary(字典),Set(集合)
不可变数据:Number(数字),String(字符串),Tuple(元组)

Number

python3支持int,float,bool,complex(复数)
python3中的整数类型全部为长整型
Python的数字类型用于存储数值
数据类型是不允许改变的,如果改变数字类型的值,将重新分配内存空间

数值运算
+-*/  //
取余 %
乘方 **

数值的除法中/ 计算结果为浮点数,//计算结果为整数

数学函数

使用的时候需要引入 math包 import math

函数返回值-描述
abs(x)返回数字的绝对值
ceil(x)返回数字的上入整数
exp(x)返回x次幂
fabs(x)返回数字的绝对值
floor(x)返回数字的下舍整数
log(x)返回数值的log
log10(x)返回以10位基数的x的对数
max(x1, x2, … )返回给定参数的最大值
min(x1, x2, … )返回给定参数的最小值
modf(x)返回x的整数部分与小数部分,整数部分以浮点数表示
pow(x, y)计算次幂
round(x, [n])返回浮点数的四舍五入值,n代表小数后的位数
sqrt(x)返回数字x的平方根
随机数函数

随机数可以用于数学,游戏,安全等领域,还经常被嵌入到算法中,用来提高算法效率, 并且提高程序的安全性。
使用时需要引入random包, import random

函数描述
choice(sqe)从序列中的元素中随机挑选一个元素
randrange([start,]stop,[step]从指定的范围内,按照指定的步长递增的集合中随机获得一个随机数,技术默认值为1
random()随机生成下一个实数,在[0,1)之间
seed([x])改变随机数生成器的种子seed
shuffle(lst)将序列的所有元素随机排序
uniform(x, y)随机生成下一个实数,在[x,y]范围内

String

Python中的字符串用单引号或者双引号括起来,使用反斜杠 \ 转义特殊字符。
注意:

  • 反斜杠可以用来转义,使用r来修饰可以让反斜杠不发生转义
  • 字符串可以使用运算符 + 进行拼接,使用运算符 * 进行重复
  • 字符串索引从左以0开始,从右以-1开始
    Python的常用字符串内建函数:
方法描述
capitalize()将字符串的第一字符转换为大写
center(width, fillchar)返回一个指定的宽度width居中的字符串,fillchar为填充的字符串,默认为空格
count(str, beg=0,end=len(string))返回str在string里面出现的次数,如果beg或end指定免责返回指定范围内str出现的次数
encode(encoding=‘UTF-8’, errors=‘strict’)以encoding指定的编码格式编码字符串,如果出错默认报一个ValueError的一场,除非errors指定的是ignor或者replace
endwith(suffix, beg=0,end=len(string))检查字符串是否以obj结束,如果beg或end指定,则检查指定范围内是否以obj结束,如果是,返回True,否则返回False
expandtabs(tabsize=8)把字符串string中的tab符号转为空格,tab符号默认的空格数是8
find(str, beg=0, end=len(string))检测str是否包含在字符串中,如果指定范围beg和end,则检查是否包含在指定范围内,如果包含则返回开始的索引值,否则返回-1
index(str, beg=0, end=len(string))跟find()方法一样,只不过如果str不在字符串中会报一个异常
isalnum()如果字符串至少有一个字符并且所有字符都是字母或数字则返回True,否则返回False
isalpha()如果字符串至少有一个字符并且所有字符都是字母则返回True,否则返回False
isdigit()如果字符串值包含数字,则返回T,否则返回F
islower()如果字符串中包含至少一个区分大小写的字符,并且所有这些字符都是小写,则返回True,否则返回False
isnumric()如果字符串中只包含数字字符,则T,否则F
isspace()如果字符串中只包含空格,则返回True,否则F
istile()如果字符串是标题化则返回T,否则返回F
isupper()如果字符串中只包含大写的字符串,则返回T,否则返回F
join(seq)以指定字符串作为分割符,将sql中所有的元素合并为一个新的字符串
len(string)返回字符串长度
ljuest(width, fillchar)返回一个原字符串左对齐,并且使用fillchar填充至长度width的新字符串,fillchar默认为空格
lower()转换字符串中的所有大写字符为小写
lstrip()去掉字符串左边的空格或指定字符
maketrans()创建字符映射的转换表,对于接受两个参数的最简单的调用方式,第一个参数是字符串,表示需要转换的字符,第二个参数也是字符串表示转换的目标
max(str)返回字符串str中最大的字母
min(str)返回字符串中最小的字母
replace(old, new [,max])将字符串中的str1替换成str2,如果max指定,则替换不超过max次
rfind(str, beg=0, end=len(string))类似于find(),不过是从右边开始
rindex(str, beg=0, end=len(string))类似于index,不过从右边开始
rjust(width [,fillchar])返回一个原字符串右对齐,并且使用fillchar(默认空格)填充至长度width的新字符串
rstrip()删除原字符串末尾的空格
split(str="", num=string.count(str))以str为分隔符截取字符串,如果num有指定值,则仅截取num+1个字符串
splitlines([keepends])按照换行回车分隔,返回一个包含各行作为元素的列表,如果参数keepends为False,不包含换行符,如果为True,则保留换行符
startswith(substr, beg=0, end=len(string))检查字符串是否是以指定字符串substr开头,如果是则返回True,否则返回False,如果beg和end指定,则在指定范围内检查
strip([chars])在字符串上执行lstrip和rstrip
swapcase()字符串中大写换小写,小写换大写
title()返回标题化的字符串,就是说所有的单词都是以大写开始,其余字母均为小写
translate(table, deletechars="")根据str给出的表,转换string的字符,要过滤掉的字符放到deletechars参数中
upper()转换小写为大写
zfill(width)返回长度为width的字符串,原字符串右对齐前面填充0
isdecimal()检查字符串是否只包含十进制字符,如果是返回true,否则返回false

List

Python中使用最频繁的数据类型,List可以完成大多数集合类的数据结构实现。List中的元素类型可以不相同,支持数字,字符串甚至可以包含列表(嵌套)
列表是写在[ ]内之间,用逗号分隔的的元素列表。
列表支持索引和截取,列表被截取之后返回一个所需元素的新列表。索引值以0为开始值,-1为从末尾开始位置。
注意:

  • 加号+是列表的连接运算符,星号*是重复操作
  • List中的元素时可变的
  • List内置了很多方法
    • append()
    • pop()
  • List 截取的时候可以接收三个参数,第三个参数为截取的步长,如果第三个数字为负数,那么表示逆向读取
    列表函数和方法
函数说明
len(list)列表元素个数
max(list)返回列表元素最大值
min(list)返回列表元素最小值
list(seq)将元组转换成列表

Python包含的方法

方法说明
list.append(obj)列表末尾添加新的对象
list.count(obj)统计某个元素在列表中出现的次数
list.extend(seq)在列表末尾一次性追加另外一个序列中的多个值,新列表扩展原来的列表
list.insert(index, obj)将对象插入列表
list.index(obj)从列表中找出某个值第一个匹配项的索引位置
list.pop(index=-1)移除列表中的一个元素(默认最后一个元素)并且返回该元素的值
list.remove(obj)移除列表中某个值的第一个匹配项
list.reverse()反向列表中元素
list.sort(key=None, reverse=False)对原列表进行排序
list.clear()清空列表
list.copy()复制列表

dictionary

字典是Python中的另外一个非常有用的内置数据类型。列表是有序的对象集合,字典是无序的对象集合。
字典的内置函数&方法

函数名说明
len(dict)计算字典元素个数,键的总数
str(dict)以字符串的形式输出字典
type(variable)返回输入的变量类型,如果是字典就返回字典类型
clear()删除字典内所有的元素
dict.fromkeys()创建一个新字典,以seq中元素作为字典的键,val为字典所有键对应的初始值
cope()返回一个字典的浅复制
get(key, default=None)返回指定键的值,如果值不存在,返回None
inkey in dict 如果键在字典中,返回true,否则返回false
dict1.items()一般列表的形式返回可遍历的(键,值)元组数组
dict1.keys()返回一个迭代器,可以使用list()转换为列表)
dict1.setdefault(key, default=None)和get类似,如果键不存在于字典中,将会添加并将值设置为default

Tuple

元组类型与列表类型类似,不同的是元组类型不能修改。元组写在小括号里面,元素之间使用逗号隔开。元组中的元素类型也可以是不同的
Tuple也可以被索引,索引从0开始,-1为末尾开始的位置,也是可以进行截取的。
虽然tuple的元素时不可以改变的,但是可以包含可变的对象,比如list。
tuple也是可以通过使用+操作符来进行
元组内置函数

方法描述
len(tuple)计算元组个数
max(tuple)返回元组中元素最大值
min(tuple)返回元组中元素最小值
tuple(iterable)将可迭代系列转换为元组

Set

集合是由一个或数个形态各异的大小整体组成的,构成集合的食物或对象称作元素或成员。Set的基本功能是进行成员关系测试和删除重复集合。
使用{} 或者set()来进行集合的创建。
集合内置方法

方法描述
add()为集合添加元素
clear()移除集合中的所有元素
copy()拷贝一个集合
difference()返回多个集合的差集
diffrence_update()移除集合中的元素,该元素在指定的集合内也存在
discard()删除集合中指定的元素
intersection()返回集合的交集
intersection_update()返回集合的交集
isdisjoint()判断两个集合是否包含相同的元素,如果没有,则返回T,否则返回F
issubset()判断指定集合是否为该方法参数集合的子集
issuperset()判断该方法的参数集合是否为指定集合的子集
pop()随机移除元素
remove()移除指定元素
symmetric_difference()返回两个集合中不重复的元素集合
symmetric_difference_update()移除当前集合中在另外一个指定集合相同的元素,并将另一个指定集合中不同的元素插入到当前集合中
union()返回两个集合的并集
update()给集合添加元素

Python数据类型转换

有时候我们需要对数据内置的类型进行转换,数据类型的转换,只需要将数据类型作为函数名即可。

函数描述
int(x [,base])将x转换成一个整数
float(x)将x转换成一个浮点数
complex(real [,imag])创建一个复数
str(x)将对象转换成字符串
repr(x)将x对象转换成表达式字符串
eval(str)计算在字符串中的有效Python表达式,并且返回一个对象
tuple(s)将序列s转换成一个元组
list(s)将序列s转换成一个列表
set(s)转变为可变集合
dict(d)创建一个字典,d必须是一ge (key,value)的元组序列
frozenset(s)转变成不可变集合
char(x)将一个整数转换成一个字符
ord(x)将一个字符转换成他的整数值
hex(x)将一个整数转换成一个十六进制字符串
oct(x)讲一个整数转换成一个八进制字符串

Python的迭代器与生成器

迭代器

迭代是Python最强大的功能之一,是访问集合元素的一种方式。
迭代器是一个可以记住遍历的位置的对象,迭代器对象从集合的第一个元素开始访问,直到所有的元素被访问完结束,迭代器只能往前不能后退。
迭代器有两个基本的方法: iter() 和next()
字符串,元组,列表都可以用于创建迭代器。

list = [1,2,3,4]
it = iter(list)
for x in it:
	print(x,end" ")

创建一个迭代器

把一个类作为一个迭代器使用需要在类中实现两个方法__iter__()和__next__()
iter()方法会返回一个特殊的迭代器对象,这个迭代器对象实现了__next__()方法并且通过stopIteration异常标识迭代的完成。
next()方法会返回下一个迭代器对象。

class MyNum:
	def __iter__(self):
		self.a = 1
		return self
	def __next__(self):
		x = self.a
		self.a +=1
		return x

生成器不但可以用于for循环,还可以被next()函数不断调用并且返回下一个值。知道最后抛出StopInteration的错误,表示无法继续下一个返回值。可以直接被作用于for循环的对象统称为可迭代对象:Iterable,可以使用isinstance()判断一个对象是否是Iterable对象。
可以被next()函数调用并且不断返回下一个值的对象称为迭代器。生成器都是Iterable对象,但是list,dict,str虽然是Iterable对象,但是却不是Iterator。
Python的Iterator对象表示的是一个数据流,Iterator对象可以被next()函数调用并且不断返回下一个数据,直到没有数据时,抛出StopIteration错误,可以吧这个数据流看成一个有序序列,但是我们却不知道序列的长度,只能不断通过next()函数实现按需计算下一个数据,所以Iterator的计算是惰性的,只有在需要返回下一个数据时,才会进行计算。

生成器

在Python中,使用了yield的函数被称为生成器。
生成器是一个返回迭代器的函数,只能用于迭代操作,生成器也是一个迭代器。在调用生成器运行的过程中,每次运行到yield时函数会暂停并且保存当前所有的运行信息,返回yield值。并且在下一次执行next()方法时,从当前位置继续运行。
调用一个生成器函数,返回的是一个迭代器对象。
如果列表元素可以按照某种算法推算出来,那么我们就可以在循环中不断推算出后续的元素,就不必再创建完成的List,可以节省很大的内存空间,Python中这种一边循环一边计算的机制,被称为生成器(Generator)

创建生成器

L = [x * x for x in range(10)]这个是列表生成式
如果我们把[]换成()就可以创建一个生成器
g = (x * x for x in range(10))
还有一种创建生成器的方式,就是使用yield关键字,当一个函数定制中包含了yield关键,那么这个函数就不再是一个普通函数,而是一个generator。
使用yield关键字定义的生成器,和函数的执行流程不一致,函数是每一行顺序执行,遇到return或者最后一条语句就返回。但是使用yield的生成器,是在每次调用next的时候执行。遇到yield就返回,再次执行的时候,则从上次返回的yield语句的地方继续执行。
比如:

def odd():
	print("第一步")
	yield 1
	print("第二步")
	yield 2
	print("第三步")
	yield 3

如此声明的odd函数就不在是一个普通的函数,遇到yield就会中断,下次又会继续执行。

Python的数据结构

列表方法使列表可以很方便的作为一个堆栈来使用,堆栈作为特定的数据结构,最先进入的元素最后被释放(后进先出),用append()可以把一个元素添加到堆的栈顶,用不指定索引的pop()方法可以把一个元素从堆栈顶释放出来。

stack = [3,4,5]
stack.append(6) # 堆栈的添加
stack.pop() # 堆栈的释放

列表也可以用来作为一个队列来使用。

from collections import deque
queue = deque(["Er", "His", "MIC"])
queue.append("Terr")
queue.poplef()

Python 模块

__name__属性
一个模块被另一个程序第一次引入时,其主程序将运行。如果我们想在模块被引入的时候,模块中的某一程序块不执行,我们可以使用__name__属性来使该程序块仅在该模块自身运行时执行。

if __name__=='__main__':
	print("程序自身在运行")
else:
	print('我来自另外一个模块')

每个模块都有一个__name__属性,当其值为__main__的时候,表明该模块自身在运行,否则是被引入。

dir()函数
内置函数dir()可以找到模块内定义的所有名称,以一个字符串列表的形式返回。
如果没有给定参数,那么dir()函数会罗列当前定义的所有名称。

Python的输入输出

Python有两种输出值的方式,表达式语句和print()函数
第三种方式是使用文件对象的write()方法,标准输出文件可以使用sys.stout引用
Python提供了input()内置函数从标准输入读入一行文本,默认的标准输入是键盘。

读和写文件

open(filename, mode) 会返回一个file对象
filename是包含了要访问的文件名称的字符串值
mode决定了打开文件的模式。

f = open('/temp/foo.txt', 'w')
f.write("Python sdasasasd")
f.close()
文件对象的方法

f.read()
为了读取一个文件的内容,调用f.read(size),这将读取一定数目的数据,然后作为字符串或字节对象返回,size是一个可选的数字类型的的参数,当size被忽略或者为负,那么该文件的所有内容都将被读取并且返回。
f.readline()
f.readline() 会从文件中读取单独的一行,换行符为‘\n’,如果返回一个空字符串,说明已经读到最后一行
f.readlines()
f.readlines()会返回文件中包含的所有行,
如果设置可选参数,则读取指定长度的字节,并且将这些字节按行分割
f.write()
f.write(string) 将string写入到文件中,然后返回写入的字符数。
f.tell()
f.tell()返回文件对象当前所处的位置,是从文件开头开始计算的字节数
f.seek()
如果要改变文件当前的位置,可以使用f.seek(iffset, from_what)函数
from_what的值,如果是0表示开头,如果是1,表示当前位置,2表示文件的结局
f,close()
用来关闭文件,释放系统的资源。

python的数据序列化和反序列化

python的pickle模块实现了基本的数据序列化和反序列化,通过pickle模块的序列化操作,我们能够将程序中运行的对象信息保存到文件中去,永久存储。
通过pickle模块的反序列化操作,我们能够从文件中创建上一次程序保存的对象

高阶函数

高阶函数的变量可以指向函数

abs(-10) # 表明我们调用abs()函数
# 而abs则表示函数本身

如果把函数本身赋给变量,那么该变量则指向函数本身,且可以通过变量进行调用。如果我们定义一个变量可以指向该函数的话,那么函数名又是什么,函数名就又成了指向该函数的变量,也就是说函数名也是变量。那么我们如果定义一个跟函数名相同的变量,就会发现定义的函数不能继续使用了。
可是我们会发现,变量可以指向函数,但是函数又是有可能有参数的。如果一个函数可以接收另外一个函数作为参数,这个函数就被称为是高阶函数。

def add(x, y, f):
	return f(x) + f(y)

高阶函数就是让函数能够接收别的函数。

map/reduce

Python內建了map()和reduce()函数。

map

map() 函数接收两个函数,一个是函数,一个是Iterable,map将传入的函数依次作用到序列的每个元素,并且把结果作为新的Iterator返回。
map()传入的第一个参数是f,即函数对象本身,由于返回的是一个Iterator,Iterator是惰性序列,因此通过list()函数让它把整个序列都计算出来并返回一个list。
map()作为高阶函数,将运算规则抽象了,可以计算任意复杂的函数。而且只需要一行代码。

reduce

reduce()把一个函数作用在一个序列上,这个函数必须接收两个参数,reduce把结果继续和序列的下一个元素做累积运算。
效果就是:reduce(f,[x1,x2,x3,x4]) = f(f(f(x1,x2),x3),x4)
比如:

from functools import reduce
def add(x, y):
	return x+y
# 如果我们执行下面的数据
reduce(add, [1,3,5,7,9])
我们得到的结果将是
25
from functools import reduce
def fn(x, y):
	return x*10 + y
def char2num(s):
	digits = {'0':0, '1':1, '2':2, '3':3, '4':4, '5':5, '6':6, '7':7, '8':8, '9':9}
	return digits[s]
reduce(fn, map(char2num, '13579'))
# map用于将13579转换成一个Iterator
# reduce 用于执行fn,将map输出的list转换成数字
13579
filter

filter()可以用来过滤序列
filter()把传入的函数依次作用于每一个元素,然后根据返回值是T或者F,来确定这个元素是留还是丢弃。
list中删除偶数,保留奇数

def is_odd(mn):
	return n%2 ==1
list(filter(is_odd,[1,2,3,4,5,6,9,10,15]))

filter()这个高阶函数,关键在于正确实现一个“筛选”函数,filter函数返回的是一个Iterator,也就是一个惰性序列,所以要强迫filter()完成计算结果,需要用list()函数获得所有结果并返回list。只有filter()在取结果的时候,才会真正筛选并每次返回下一个筛选出的元素。

返回函数

高阶函数除了可以接受函数作为参数外,还可以作为结果值返回

装饰器

函数也是一个对象,而且函数是可以被赋值给变量,所以通过变量也可以调用函数。

def now():
	prin('当前时间')

f = now
f()
当前时间

如果我们想要增强函数的功能,比如在函数调用前后自动打印日志,但是又不想去修改now的函数的定义。这种在代码运行期间动态增加函数的方式,被称为装饰器。
本质上装饰器就是一个返回函数的高阶函数
定义方式比如

def log(func):
	def wrapper(*args,**kw):
		print("call %s()" %func.__name__)
		return func(*args, **kw)
	return wrapper

使用:

@log
def now():
	print("2020-05-31")

当调用now函数的时候,不仅会运行now()函数本身,还会再now函数运行前打印一行日志。
将@log放到now()函数的定义的地方相当于执行了语句now = log(now)
又由于log()是一个装饰器,返回一个函数,所以原来的now()函数仍然存在,只是现在同名的now变量指向了新的函数,于是调用now()将执行新的函数,即在log中返回的wrapper函数
如果装饰器本身需要传入参数,那就要编写一个返回装饰器的高阶函数

def log(text):
	def decorator(func):
		def wrapper(*args, **kw):
			print("%s %s()" %(text, func.__name__))
			return func(*args, **kw)
		return wrapper
	return decorator
import functools
def log(func):
	@functools.wrap(func)
	def wrapper(*args, **kw):
		print("call %s()" %func.__name__)
		return func(*args, **kw)
	return wrapper
import functools
def log(text):
	def decorator(func):
		@functools.wraps(func)
		def wrapper(*args, **kw):
			print("%s %s()" %(text, func.__name__))
		return wrapper
	return decorator

偏函数

当函数的参数个数太多,需要简化的时候,使用functiontools.partial可以创建一个新的函数,这新的函数可以固定住原函数的部分参数,从而在调用时更简单。

import functools
int2 = functools.partial(int,base=2)

这样就是使用functools.partial()方法作用于int函数,并且将base参数固定为2,来生成int2函数。

面向对象

数据封装、继承和多态是面向对象程序设计的三个概念。
当子类继承父类的时候子类就具有了父类的能力,当A的子类B和C。当我们创建子类B和C的时候可以使用A来进行创建,都可以用A来操作 ,这时就是多态了。
对于Python动态语言来讲,我们并不一定要传入A的子类或者孙子类的类型。只要类中包含A中的方法,我们调用A中同名的方法的时候,也可以传入非A子类的类进行方法调用,这就是Python中的鸭子类型。动态语言的鸭子类型:一个对象只要“看起来像鸭子,走起路来像鸭子”那他就可以被看做是鸭子类型。
多重继承,通过多重继承,一个子类就可以同时获得多个父类的所有功能。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值