本篇文章的主要内容为内置函数、匿名函数、递归函数、面向对象基础知识、面向对象的组合、面向对象的继承以及面向对象的多态。
1.内置函数
''' 整体说明: 01 研究python的内置函数。 02 以下内置函数都是常用的,并且比较重要的。 ''' # 01 locals:当前作用域的所有的变量 ** # 0101 当作用域为全局变量,输出全局的变量。 name = '太白' age = 25 def func1(): a1 = 'Ws' b1 = {'name': '马玉刚'} func1() print(locals()) # 打印出所有的全局变量,以字典的形式输出,其中name = '太白' # 0102 当前作用域为局部变量,输出局部的变量。 name = '太白' age = 25 def func1(): a1 = 'Ws' b1 = {'name': '马玉刚'} print(locals()) # 打印函数func1的局部变量,以字典的形式输出,其中name = '马玉刚' func1() # 02 globals: 永远获取的是全局作用所有的变量等。 ** name = '太白' age = 25 def func1(): a1 = 'Ws' b1 = {'name': '二狗'} print(globals()) # 打印出所有的全局变量,以字典的形式输出,其中name = '太白' func1() print(globals()) # 打印出所有的全局变量,以字典的形式输出,其中name = '太白' # 03 eval:执行字符串类型的代码,并返回最终结果。(慎用:由于采用用户输入或者接口对接的时候如果不校验直接执行的话, 则比较容易被黑客作为攻击的入口) eval('2 + 2') # 4 n = 81 eval("n + 4") # 85 eval('print(666)') # 666 # 04 exec:执行字符串类型的代码 (慎用:原因同上) s = ''' for i in [1,2,3]: print(i) ''' exec(s) #04 print 输出 ''' 源码分析 def print(self, *args, sep=' ', end=' ', file=None): # known special case of print """ print(value, ..., sep=' ', end=' ', file=sys.stdout, flush=False) file: 默认是输出到屏幕,如果设置为文件句柄,输出到文件 sep: 打印多个值之间的分隔符,默认为空格 end: 每一次打印的结尾,默认为换行符 flush: 立即把内容输出到流文件,不作缓存 """ ''' print(111, 222, 333, sep='*') # 111*222*333 print(111, end='') print(222) # 两行的结果 111222 f = open('log', 'w', encoding='utf-8') print('写入文件', file = f, flush=True) # 05 hash:获取一个对象的哈希值(可哈希对象:int,str,Bool,tuple) print(hash(12322)) print(hash('123')) print(hash('arg')) print(hash('alex')) print(hash(True)) print(hash(False)) print(hash((1, 2, 3))) ''' 执行结果: 12322 -2996001552409009098 -4637515981888139739 2311495795356652852 1 0 2528502973977326415 ''' 06 open:函数用于打开一个文件,创建一个 file 对象,相关的方法才可以调用它进行读写。 07 __import__ :模块相关,函数用于动态加载类和函数 # 08 help:用于查看函数或模块用途的详细说明。 print(help(str)) # 09 callable 判断对象是否可调用,如果返回True,object仍然可能调用失败;但如果返回False,调用对象ojbect绝对不会成功。 ** a1 = 'barry' def func1(): print(666) print(callable(a1)) # False print(callable(func1)) # True # 10 dir :查看内置属性,函数不带参数时,返回当前范围内的变量、方法和定义的类型列表;带参数时,返回参数的属性、方法列表。 # 如果参数包含方法__dir__(),该方法将被调用。如果参数不包含__dir__(),该方法将最大限度地收集参数信息。 dir print(dir('alex')) # 11 进制转换(3)(1)bin:将十进制转换为二进制并且返回。(2)oct:将十进制转换为八进制字符串并返回。(3)hex:将十进制转换为十六进制字符串并返回。 print(bin(10), type(bin(10))) # 0b1010 <class 'str'> print(oct(10), type(oct(10))) # 0o12 <class 'str'> print(hex(10), type(hex(10))) # 0xa <class 'str'> # 12 数学运算共7个:abs,divmod,round,pow,sum,min,max # abs:函数返回数字的绝对值。 # divmod:计算除数与被除数的结果,返回一个包含商和余数的元组(a // b, a % b)。分页会用到,返回商数和余数。** print(divmod(7, 3)) # (2,1) # round:保留浮点数的小数位数,默认保留整数。 # pow:求x**y次幂。 # sum:对可迭代对象进行求和计算(可设置初始值)。 print(sum([i for i in range(10)])) # 默认初始值是0,输出结果为45. print(sum([i for i in range(10)], 100)) # 设置默认初始值为100,输出结果为145。 # min:返回可迭代对象的最小值(可加key,key为函数名,通过函数的规则,返回最小值)。 *** # 常规式的输出最小值 print(min(1, 2, 3, 4, 5)) print(min([1, 2, 3, 4, 5])) print(min([('alex', 3), ('太白', 1), ('wS', 2)])) # 按照unicode编码去比较大小,首先比较每个元素中的第一个,之后逐个比较,直至比较出大小来即可。 # 加key的输出最小值(key为函数名) # min 默认将可迭代对象中的每个元素依次传入函数中,按照函数的返回值去取最小元素。 l1 = [('alex', 3), ('太白', 1), ('wS', 2)] def func(x): return x[1] # min将可迭代对象中的每个元素依次传入函数中,并且按照返回值取最小元素。该返回值是将列表中每个元素的第二个作为返回值返回。 print(min(l1, key=func)) # ('太白', 1) # # max:返回可迭代对象的最大值(可加key,key为函数名,通过函数的规则,返回最大值)。 *** # max的使用和min一样。 # 13 reversed:将一个序列翻转,返回一个新的翻转的迭代器。 *** l1 = [2, 3, 4, 1] l2 = reversed(l1) print(list(l2)) # 14 format 字符串可以提供的参数,指定对齐方式,<是左对齐, >是右对齐,^是居中对齐。 print(format('test', '<20')) # 以20个字符为长度,进行左对齐 print(format('test', '>20')) print(format('test', '^20')) # 15 bytes:用于不同编码之间的转化。 ** s1 = '太白' # unicode ---> utf-8 bytes b1 = s1.encode('utf-8') print(b1) # utf-8 bytes ---> unicode s2 = b1.decode('utf-8') print(s2) s1 = '太白' # unicode ---> utf-8 bytes b1 = bytes(s1, encoding='utf-8') print(b1) # 16 ord:输入字符找该字符编码的位置 print(ord('中')) # 20013 print(ord('a')) # 97, # 17 chr:输入位置数字找出其对应的字符 print(chr(97)) # a print(chr(20013)) # 中 #18 ascii:是ascii码中的返回该值,不是就返回/u... print(ascii('a')) # 'a' print(ascii('中')) # 'u4e2d' # 19 repr:返回一个对象的string形式(原形毕露)。 s1 = "alex" l3 = '[1,2,3]' print(s1) # alex print(l3) # [1,2,3] print(repr(s1)) # 'alex' print(repr(l3)) # '[1,2,3]' # 20 %r-也会使字符串原型毕露,用处是引用别人说的话时,如果需要保留单引号的时候,就需要用%r。 s1 = '我叫%s, 我是%r' % ('alex', 'sb') print(s1) # 21 sorted:对所有可迭代的对象进行排序操作。 l1 = [1, 2, 7, 6, 5, 4] l2 = sorted(l1) print(l2) # [1, 2, 4, 5, 6, 7] l1 = [('alex', 3), ('太白', 1), ('wS', 2), ('wS', 4)] def func(x): return x[1] new_l = sorted(l1, key=func, reverse=True) # sorted:将可迭代对象中的每个元素依次传入函数中,并且将每个元素中的第二个返回进行排序,同时进行倒序输出。 print(new_l) # [('wS', 4), ('alex', 3), ('wS', 2), ('太白', 1)] # 22 # enumerate::枚举,返回一个枚举对象。 *** l1 = ['太白%s' % i for i in range(10)] for index, i in enumerate(l1, 10): # 设置默认索引数字从10开始,i从0开始进行循环 print(index, i) # 23 all:可迭代对象中,全都是True才是True ** print(all([1, 2, True, 100])) # True # 24 any:可迭代对象中,有一个True 就是True ** print(any(['', 0])) # False ''' # 24 zip 函数用于将可迭代的对象作为参数,将对象中对应的元素打包成一个个元组,然后返回由这些元组组成的列表。 如果各个迭代器的元素个数不一致,则返回列表长度与最短的对象相同。 *** ''' l1 = [1, 2, 3, 6, 7, 8, 9] l2 = ['a', 'b', 'c', 5] l3 = ('*', '**', (1, 2, 3)) print(zip(l1, l2, l3)) # 生成一个可迭代对象 for i in zip(l1, l2, l3): print(i) ''' <zip object at 0x0000000001E95608> (1, 'a', '*') (2, 'b', '**') (3, 'c', (1, 2, 3)) ''' # 25 filter 返回是迭代器 类比成列表推导式:筛选模式 *** l1 = [i for i in range(100) if i % 2 == 0] print(l1) l2 = [1, 2, 3, 4, 5, 6] def func(x): return x % 2 == 0 # 筛选条件 obj1 = filter(func, l2) print(list(obj1)) # [2, 4, 6],切记一定要加上list,否则只是一个迭代器。 # 26 map: 返回一个迭代器 类比成列表推导式:循环模式 *** l1 = [1, 2, 3, 4, 5, 6] def func(x): return x ** 2 # 返回值 print(list(map(func, l1)))
2.匿名函数
''' 整体说明; 01 一句话函数,一行代码实现的函数 02 格式:函数名 = lambda 输入:返回值 ''' # 01 计算两个数字的和 func1 = lambda x, y: x + y print(func1(2, 3)) # 02 三个数的运算 func2 = lambda x, y, z: (x + y - z) * 2 print(func2(2, 5, 6)) # 03 匿名函数与内置函数结合使用 l1 = [1, 2, 3, 4, 5, 6] obj1 = filter(lambda x: x % 2 == 0, l1) print(obj1) # <filter object at 0x00000000021AE2E8>,直接打印是一个迭代器 print(list(obj1)) # 打印一个列表[2, 4, 6] # 04 输出字典种value最大的key l = [3, 2, 100, 999, 213, 1111, 31121, 333] dic = {'k1': 10, 'k2': 100, 'k3': 30} ret = max(dic, key=lambda x: dic[x]) print(ret)
3.递归函数
''' 整体说明: 01 自己用自己。 02 默认的递归次数:999(998) 03 递归函数一定要有返回值(返回值基本上都是函数自己调用自己) ''' # 01 用递归函数实现斐波那契数列 # 1 1 2 3 5 8 13 21 ..... # 1 2 3 4 5 6 7 8 ..... def fib(n): if (n == 1 or n == 2): return 1 else: return fib(n - 1) + fib(n - 2) print(fib(20)) ''' 推到过程: fib(3) = fib(2) + fib(1) fib(4) = fib(3) + fib(2) 。。。。 fib(n) = fib(n - 1) + fib(n - 2) '''
4.面向对象基础知识
''' 整体说明: 01 相同功能的函数进行分类。 02 面向对象的特点: (1)它是将某些相关的功能(函数)封装到一起。 (2) 站在上帝的角度,创建一个公共模板,然后通过模板创造不同的对象。 03 类:具有相同属性和技能的一类事物。 04 对象:类的具体表现。 05 类的分析方法: (1)结构分析:类一般分为两个部分,即静态变量(静态属性/静态字段),动态方法(函数)。 (2)思想分析:创建一个类的公共模板,通过创建个体对象可以享有公共方法。 06 类的调用:类中的静态属性一般通过类名去调用或者改变;类中的动态方法一般通过对象去执行。 07 类名的应用 (1)类名调用类中的静态属性。 a)方法一:__dict__ 只能查询(不能增删改) 类中所有的静态属性,动态方法。 b)方法二: 万能的点 . 可以查,可以改,可增,可删。 (2)类名执行类中的动态方法。(一般不建议用类名执行,除非是特殊方法:类方法,静态方法) 08 实例化对象:类名+()就是一个实例化对象的过程,具体步骤如下: (1)实例化对象在内存中产生一个对象空间(内存地址)。 (2)自动执行 __init__方法并且将对象空间传给了self参数。*** (3)在 __init__方法中,给对象空间封装一些静态属性。 09 对象的应用 (1)对象调用类的静态属性 (2)万能的点: .可以调用类中的静态属性。 (3)对象执行类中动态方法: 10 self 约定俗成 self,类中的方法的第一个参数要设定为self,在对象调用方法时,会自动将对象空间传给self。 11 __init__方法:作用是给对象封装属性。 ''' # 01 定义一个类person class Person: mind = '有思想' animal = '高级动物' language = '文字语言' # 静态属性,静态变量 静态字段 def work(self): # 函数 方法,动态方法,动态属性。 print('人类都会工作') def eat(self): print('人类都需要吃饭') # 02 类名的应用 # 0201 类名调用类中静态属性 class Person: mind = '有思想' animal = '高级动物' language = '文字语言' # 静态属性,静态变量 静态字段 def work(self): # 函数 方法,动态方法,动态属性。 print('人类都会工作') def eat(self): print('人类都需要吃饭') # 方法一:__dict__ 只能查询(不能增删改) 类中所有的静态属性,动态方法。 print(Person.__dict__) print(Person.__dict__['mind']) Person.__dict__['mind'] = '无思想的' # 不能这样修改,因为方法一只能查询,不能增删改 print(Person.__dict__) # 方法二: 万能的点 . 可以查,可以改,可增,可删。 print(Person.animal) Person.animal = '低级动物' # 修改类中的静态属性 Person.name = '有姓名' # 增加类中的静态属性 print(Person.animal) del Person.animal # print(Person.animal) # 报错,因为上一步已经删除类Person中animal静态属性,所以会报错。 print(Person.__dict__) # 0202 类名执行类中的动态方法 (一般不建议用类名执行,除非是特殊方法:类方法,静态方法) Person.work('alex') # 不建议用类名执行动态方法。 # 03 __init__:作用是给对象封装属性。 # 以下是定义游戏角色的类Game_Role class Game_Role: a1 = '英雄联盟' name = '太白' def __init__(self, name, sex, ad, hp): # __init__方法,特殊方法: 给对象封装属性 # print(self) # print(666) ''' 以下给对象封装的属性''' self.name = name self.sex = sex self.ad = ad self.hp = hp def fight(self,*args, **kwargs): pass gailun = Game_Role('盖伦', 'man', 30, 500) # 进行对象的实例化,即gailun = Game_Role,默认执行__init__函数,给对象封装属性。 print(gailun.name) # 通过万能的点,由实例化的对象进行静态属性的展示。 # 04 对象的应用。 # 0401 对象调用类中的静态属性;通过万能的点:.可以调用类中的静态属性。 print(gailun.name) # 通过万能的点,由实例化的对象进行静态属性的展示。 # 0402 对象执行类中的动态方法。 class Game_Role: a1 = '英雄联盟' name = '太白' def __init__(self, name, sex, ad, hp): # __init__方法,特殊方法: 给对象封装属性 # print(self) # print(666) ''' 以下给对象封装的属性''' self.name = name self.sex = sex self.ad = ad self.hp = hp def fight(self,*args, **kwargs): pass def work(self): self.hobby = '大刀' # 增加对象的属性 print(self.__dict__) gailun = Game_Role('盖伦', 'man', 30, 500) # 进行对象的实例化,即gailun = Game_Role,默认执行__init__函数,给对象封装属性。 gailun.work() print(gailun.hobby) # 大刀 # 0403 对象查看自己的空间属性 # 查看全部:__dict__ # 查看某个对象自己的静态属性:万能的点,实现增删改查。 print(gailun.name) print(gailun.sex) gailun.name = 'GAIlun' gailun.hobby = '大刀' print(gailun.hobby) print(gailun.__dict__)
5.面向对象组合
''' 整体说明: 01 对象与对象之间是不能相互访问的, 彼此独立。 02 对象可以访问类中的所有内容,但是类名不能访问对象中的内容。 03 组合的作用:让类的对象和另一个类的对象发生关联,从而可以互相访问。(通过一个对象的属性是另一个类的对象来实现) ''' ''' 程序说明: 01 定义了两个类,即角色类和武器类,其中角色类中的ad代表攻击力,hp代表血量。 02 需求是盖伦使用大宝剑攻击沟通一次(只计算工具本身对狗头血量的消耗,暂时忽略盖伦本身的攻击力) ''' class Game_Role: area = '召唤师峡谷' def __init__(self, name, sex, ad, hp): self.name = name self.sex = sex self.ad = ad # 攻击力 self.hp = hp # 血量 def fight(self, role1): role1.hp = role1.hp - self.ad print('%s 攻击 %s, %s还剩余%s' % (self.name, role1.name, role1.name, role1.hp)) # print(self, role1) def equit_weapon(self, wea): # 组合: 对象中的属性是另一个类的对象,将Weapon类的对象sword作为Game_roles类的实例化对象P1的封装的属性。 self.wea = wea class Weapon: def __init__(self, name, ad): self.name = name self.ad = ad def wea_attack(self, role1, role2): role2.hp = role2.hp - self.ad print('%s 利用 %s 攻击 %s, %s还剩余%s' % (role1.name, self.name, role2.name, role2.name, role2.hp)) p1 = Game_Role('盖伦', 'man', 30, 500) p2 = Game_Role('狗头', '公', 50, 250) # p3 = Game_Role('诺克', 'man', 50, 350) # p1.fight(p2) sword = Weapon('大宝剑', 40) # print(sword) # sword.wea_attack(p1, p2) p1.equit_weapon(sword) # 此方法就是给p1对象封装一个属性,属性值是sword对象 # print(p1.wea.name) # # print(p1.wea) p1.wea.wea_attack(p1, p2) # 通过p1.wea找到sword 然后在sword.wea_attack执行方法,其中self省略了。
6.面向对象的继承
''' 整体说明: 01 继承的作用: (1)节省代码 (2)提高效率 (3)让类之间产生关联 02 继承的分类 (1)单继承 (2)多继承 03 类的分类 (1)经典类:不继承object的类。 (2)新式类:默认继承object类 (3)说明:python2x中经典类和新式类共存;python3x中全部都是新式类 04 在继承的时候,执行的顺序是先在子类/派生类中寻找收含有变量,如果含有则直接输出,如果不含有,则根据“类对象指针”寻找 父级中是否含有该变量,如果有则直接输出,如果不含有,则继续寻找父级的父级中是否含有该变量,直至遍历了所有的父级类,仍 没有则报错。 05 两种方法解决既要执行子类的方法,又要执行父类的方法 (1)方法一:直接调用另一个类的方法 (2)方法二:使用super() 自动将self传给父类的self ''' # 01 单继承 ''' 说明: 01 Animal是父类/基类Person是子类/派生类。 ''' # 0101 单继承说明 class Animal: a1 = '太白' def __init__(self, kind, age, sex): self.kind = kind self.age = age self.sex = sex def func1(self): print(666) class Person(Animal): a1 = 'alex' # 由于子类中含有该变量,所以直接输出变量值 alex,不会根据类对象指针去寻找父级类中是否含有该变量。 pass print(Person.a1) # 0102 单继承说明 ''' 两种解决方式解决既要执行子类的方法,又要执行父类的方法 01 第一种 Animal.__init__(self, k1, a1, s1) 直接调用另一个类的方法 02 第二种:super().__init__(k1,a1,s1) # 自动将self传给父类的self ''' class Animal: def __init__(self, kind, age, sex): self.kind = kind self.age = age self.sex = sex def bark(self): print('动物都会叫') class Dog(Animal): def __init__(self, k1, a1, s1, bite): ''' self = d1 k1 = '藏獒' .... ''' Animal.__init__(self, k1, a1, s1) # 方法一:Animal.__init__(self, k1, a1, s1) 直接调用另一个类的方法 # super().__init__(k1, a1, s1) # 方法二: 自动将self传给父类的self self.bite = bite # 新增Dog的属性,咬合力 bite def bark(self): super().bark() # 调用父类(超类)中需要执行的动态方法。 print('汪汪汪') class Cat(Animal): def bark(self): print('喵喵喵') class chick(Animal): def bark(self): print('大爷,来玩呀') d1 = Dog('藏獒', 3, '公', 300) # 类Dog的实例化对象d1。 d1.bark() # 对象执行类中的动态方法。 # 02 多继承 # 新式类:C3算法 mro 主要是查询 新式类的多继承的继承顺顺序 class A: def func(self): print(666) pass class B: def func(self): print(666) pass class C(A): def func(self): print(666) pass class D(B): def func(self): print(666) pass class E(C,D): # def func(self): # print(666) pass e1 = E() # e1.func() print(E.mro())
7.面向对象的多态
''' 整体说明: 01 Pyhon不支持Java和C#这一类强类型语言中多态的写法,但是原生多态。 02 Java或C#中定义函数参数时,必须指定参数的类型,而python不需要强制制定数据类型。 '''