1. 函数
1. 函数的作用 : 保存某段程序.某个代码片段.提升代码的可读性,让代码复用。
2. 函数使用包含两个步骤:
1.定义函数 ----在函数中编写代码,实现功能
def 函数名():
函数封装的代码
2.调用函数 ----执行编写的代码
函数名()
>>> def test(a,b):
... "用来完成对2个数求和"
... print("%d"%(a+b))
...
>>>
>>> test(11,22)
33
3. 函数的参数
1.在定义函数后面的小括号中写的叫参数(形参).
2.形数就是给将调用函数的真实数据作占位.
3.函数调用时,里面写的数据叫真实数据(实参)
4.如果函数设置了参数,在调用函数时必须传对应的真实数据.
4.全局变量和局部变量
# 全局变量:在函数外面定义的所用人都能使用
# 全局变量作用于整个代码,最好不要和形参同名.
# 形参的作用域(可使用的范围) 只能函数内部
# 函数内部定义
# 不同函数的形参名可以是同名的,相互不影响.
# 在函数内部 可以使用global 关键字 定义全局变量
# 可以使用一次global对多个全局变量进行声明
global a, b
# 还可以用多次global声明都是可以的
# global a
# global b
5. 函数的返回值 -- return
返回值----把函数的执行结果返回出来,(如果需要使用执行结果,就返回它,赋值给一个变量)
#⼀个函数中可以有多个return语句,但是只要有⼀个return语句被执⾏,那么这个函数就会结束
# return后面可以是元组,列表、字典等,只要是能够存储多个数据的类型,就可以一次性返回多个数据
def function():
# return [1, 2, 3]
# return (1, 2, 3)
return {"num1": 1, "num2": 2, "num3": 3}
## 如果return后面有多个数据,那么默认是元组
#如果使用多个变量接收返回值,python会自动将元组拆包成单个数据.
# 返回值两个作用:1.把结果返回出去 2.终止下面程序的运行
6. 函数的嵌套调用
一个函数里面调用了另一个函数
7. 元祖的拆包和组包
解包也叫拆包 —— 把元组分解开 多个元组对应多个变量,就能解包
自动组包 —— 自动组合成 元组 一个变量,对应多个值,就会自动组包
# 组包 与 解包
a = 1, 2, 3
print(a) # (1, 2, 3)
x, y, z = a
print(x, y, z) # 1 2 3
8. 函数参数
1) 缺省参数(默认参数)
def printinfo(name, age=35):
print(.....)
如果 age 没有被传入,会打印默认的 age
# 总结: 在形参中默认有值的参数,称之为缺省参数;
缺省参数都写在最后面,可以被传参所改变。
2) 关键字参数: 不管形参顺序,都能正确传参,自动去找形参进行赋值
(函数调用使用关键字参数来确定传入的参数值。)
def printme( str ):
"打印任何传入的字符串"
print str;
return;
#调用printme函数
printme( str = "My string");
3)不定长参数 :
*args 随便你传多少个参数,输出默认都是元组格式;
**kwargs 转门接收未定义形参的关键字参数,把他们变成字典.
# 注意: 如果很多个值都是不定长参数,那么这种情况下,可以将缺省参数放到 *args的后面, 但如果有**kwargs的话,**kwargs必须是最后的
# # 函数的参数传递
def fun2(a, *args, b=5, **kwargs):
print('参数:{}, {}'.format(a, b))
x, y = args
print(args)
print(x, y)
print(kwargs)
dic = kwargs
for i in dic.values():
print(i)
fun2(2, 3, 4, b=9, d='dd', g='il')
## output
参数:2, 9
(3, 4)
3 4
{'d': 'dd', 'g': 'il'}
dd
il
9. 可变、不可变类型
可变类型有: 列表、字典、集合 (修改时,内存地址不发生那个改变)
不可变类型有: 数字、字符串、元组 (修改时,内存地址发生改变)
10. 递归函数
如果一个函数在内部不调用其它的函数,而是自己本身的话,这个函数就是递归函数
11. 匿名函数
没有名字的函数,只能返回一个结果。相当于函数的简写方法。
# fun1= lambda 参数1,参数2 :返回值(需要得到的表达式或者值)
>>> fun1=lambda a,b : a+b
>>> fun1(2,3)
5
12. 列表推导式 -- 轻量级循环创建列表
list1 = [把每一次循环过后的值,赋值到这 for 变量名 in 循环的次数]
#生成一个 0-100的列表 list1 = [a for a in range(101)]
13. 文件的读写
1) 写数据 write
f = open('test.txt', 'w')
f.write('hello world, i am here!')
f.close()
简单写法: with open("test.txt","w") as f:
f.write('hello world')
2) 读取方式 :
read(5) 一个一个字的进行读取,如果读大文件比较费劲, 可添加读取位数.
readlines() 一行一行读取,把每一行变成一个列表中的数据.如果想得到每一行,可用遍历把数据都输出来. (自带有\n(换行符))
readline() 默认只读一行数据,加循环可以重复读取多行数据.
### 读大文件时:读取多行用 .readlines() 只读一行用 .readline()
r 以只读方式打开文件。文件的指针将会放在文件的开头。这是默认模式。
w 打开一个文件只用于写入。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
a 打开一个文件用于追加。如果该文件已存在,文件指针将会放在文件的结尾。也就是说,新的内容将会被写入到已有内容之后。如果该文件不存在,创建新文件进行写入。
r+ 打开一个文件用于读写。文件指针将会放在文件的开头。没有该文件会报错
w+ 打开一个文件用于读写。如果该文件已存在则将其覆盖。如果该文件不存在,创建新文件。
a+ 打开一个文件用于读写。如果该文件已存在,文件指针将会放在文件的结尾。文件打开时会是追加模式。如果该文件不存在,创建新文件用于读写。
# # 文件的写入
# with open('test01.txt', "w") as f:
# f.write('hello')
# 文件的读取
# with open('test01.txt', 'r') as f:
# print(f.read(3))
# 文件的追加
with open('test01.txt', 'a') as f:
f.write('\n world')
14. 面向对象
一:类 :描述共同行为的集合。
#类是总结事物特征的抽象概念,而对象是具体存在的某个实物
定义类 class 类名 (类名一般使用大驼峰)
def eat(self) 方法。定义对象的共同行为。(会自动添加第一个形参self)
创建对象 dog1 = Dog() # 用类创建对象 格式: 对象名= 类名()
dog1.eat() # 调用对象的方法 格式: 对象名.方法()
class Dog(object): # 定义一个类 类名 的命名规则按照"大驼峰命名法"
def __init__(self, name): # 初始化方法
self.name = name
def __str__(self):
return "{}是一条非常友好的狗狗".format(self.name)
def eat(self): # 类里面的 实例方法
print('喜欢吃肉')
dog1 = Dog("小黄") # 创建对象
dog1.eat() # 调用类的用实例方法
print(dog1.name) #小黄
print(dog1) # 小黄是一条非常友好的狗狗(有魔法方法__str__ ,打印对象会调用 str方法)
self 关键字
1.self 表示当前调用该方法的对象
2.在方法中使用对象的属性时,用self来访问,不要直接去用对象访问.
3.Python解释器会隐式的将调用方法的对象作为第一个实参进行传递.
对象 包括: 1)属性 用于记录与对象相关的数据
2)方法 用于实现与对象相关的操作
例子 :
class Hero(object): # 新式类定义形式
"""info 是一个实例方法,类对象可以调用实例方法,实例方法的第一个参数一定是self"""
def info(self):
"""当对象调用实例方法时,Python会自动将对象本身的引用做为参数,
传递到实例方法的第一个参数self里"""
print(self)
print("self各不同,对象是出处。")
# Hero这个类 实例化了一个对象 taidamier(泰达米尔)
taidamier = Hero()
# 对象调用实例方法info(),执行info()里的代码
# . 表示选择属性或者方法
taidamier.info()
print(taidamier) # 打印对象,则默认打印对象在内存的地址,结果等同于info里的print(self)
print(id(taidamier)) # id(taidamier) 则是内存地址的十进制形式表示
# 如果有 __str__ 方法: print(对象)或类里面的 print(self) 会走 str 里面的方法
二 : 有参数的 __init__() 方法:
class Hero(object):
"""定义了一个英雄类,可以移动和攻击"""
def __init__(self, name, skill, hp, atk, armor):
""" __init__() 方法,用来做变量初始化 或 赋值 操作"""
# 英雄名
self.name = name
# 技能
self.skill = skill
# 生命值:
self.hp = hp
# 攻击力
self.atk = atk
# 护甲值
self.armor = armor
def move(self):
"""实例方法"""
print("%s 正在前往事发地点..." % self.name)
def attack(self):
"""实例方法"""
print("发出了一招强力的%s..." % self.skill)
def info(self):
print("英雄 %s 的生命值 :%d" % (self.name, self.hp))
print("英雄 %s 的攻击力 :%d" % (self.name, self.atk))
print("英雄 %s 的护甲值 :%d" % (self.name, self.armor))
# 实例化英雄对象时,参数会传递到对象的__init__()方法里
taidamier = Hero("泰达米尔", "旋风斩", 2600, 450, 200)
gailun = Hero("盖伦", "大宝剑", 4200, 260, 400)
# print(gailun)
# print(taidamier)
# 不同对象的属性值的单独保存
print(id(taidamier.name))
print(id(gailun.name))
# 同一个类的不同对象,实例方法共享
print(id(taidamier.move()))
print(id(gailun.move()))
## 不同对象的属性值的单独保存;实例方法共享
## 1. 通过一个类,可以创建多个对象;
2. __init__(self)
中,默认有1个参数名字为self,如果在创建对象时传递了2个实参,那么__init__(self)
中出 self作为第一个形参外还需要2个形参,例如__init__(self,x,y)
3. 在类的内部获取 属性 和实例方法,通过 self 获取;
4. 在类外部获取 属性 和实例方法,通过对象名获取;
5.
如果一个类有多个对象,每个对象的属性是各自保存的,都有各自独立的地址;
6.
但是实例方法是所有对象共享的,只占用一份内存空间。类会通过self来判断是哪个对象调用了实例方法。
三. 魔法方法: __单词__(self) 不需要调用,在特殊情况下自动调用
__init__ 当对象创建时会自动调用,init定义的参数,是在创建对象的小括号中传递.
__str__ 直接打印对象时,会被自动调用,里面必须写return,必须要返回字符串 (如果没有 __str__ 则默认打印 对象在内存得地址).
__del__ 当对象被销毁前,会被自动调用
四. 继承: 简化代码;只要是继承了,那么就能够得到父类的所有的方法和属性。
## 1. 创建类的时,python 默认就会帮你去继承 object; object 叫作 基类。
## 2. 语法格式 : class子类名(写上要继承的类/父类)
## 3. B类如果继承了A类,那么A类就是B类的父类/基类,反之,B是A的子类.
(一个类,可以同时继承多个类;优先继承第一个类)
# 父类
class A(object):
def __init__(self):
self.num = 10
def print_num(self):
print(self.num + 10)
# 子类
class B(A):
pass
b = B() # 创建子类对象
print(b.num) # 子类对象调用父类的属性
b.print_num() # 子类对象调用父类的方法
# mro 查看继承关系
print(B.__mro__) (<class '__main__.B'>, <class '__main__.A'>, <class 'object'>)
## 1. 多继承可以继承多个父类,也继承了所有父类的属性和方法
2. 如果多个父类中有同名的 属性和方法,则默认使用第一个父类的属性和方法(根据类的魔法属性mro的顺序来查找:类名.__mro__)
3. 多个父类中,不重名的属性和方法,不会有任何影响。
五. 重写父类 : 在子类中定义一个和父类同名的方法,就叫作重写父类。
如果子类中有和父类同名的方法,将来执行时,子类会优先调用自己里面的方法.
继承链: 当前类à 直接父类à…….._--> object所有类的基类
## 调用被重写的父类方法
子类重写了父类的方法, 仍然想执行父类中的方法,则可以在类中使用super()来调用方法.
def 方法名:
方法一 : 父类.方法名(self)
方法二: super (子类,self).方法名 ( ) 括号里面找的是当前类的父类
方法三: super().方法名 ( ) 直接调用super函数,会直接找当前的父类,即继承中的下一个类/父类
# 类的继承
class A(object):
def action(self):
print('我是 A 的方法')
class B(A):
def action(self):
print("我是 B 的方法")
def demo(self):
# 子类重写了父类的方法,还想调用父类的方法
# A.action(self) # 方式一
# super(B, self).action() # 方式二
super().action()
C = B()
C.action() # 我是 B 的方法
C.demo() # 我是 A 的方法
六. 私有权限
面向对象的 三大特征:封装 , 继承 , 多态
封装的意义:
- 将属性和方法放到一起做为一个整体,然后通过实例化对象来处理;
- 隐藏内部实现细节,只需要和对象及其属性和方法交互就可以了;
- 对类的属性和方法增加 访问权限控制。
私有权限:在属性名和方法名 前面 加上两个下划线 __
- 类的私有属性 和 私有方法,都不能通过对象直接访问,但是可以在本类内部访问;
- 类的私有属性 和 私有方法,都不会被子类继承,子类也无法访问;
- 私有属性 和 私有方法 往往用来处理类的内部事情,不通过对象处理,起到安全作用。
多态(鸭子类型): 继承或调用不同的类,会有不同的状态.既可以调用父类,也可以调用子类.