赞
踩
所谓函数,就是把 具有独立功能的代码块 组织为一个小模块,在需要的时候 调用
函数的调用包括两个步骤:
1.定义函数一一封装 独立的功能
2.调用函数一一享受 封装 的成果
函数的作用,在开发程序时,使用函数可以提高编写的效率以及代码的 重用
1.def 是英文 define(定义) 的缩写
2.函数名称 应该能够表达 函数封装代码 的功能,方便后续的调用
3.函数名称 的命名应该 符合 标识符的命名规则
可以由字母、下划线和数字组成
不能以数字开头
不能与关键字重名

开发一个 sum_2_num 的函数
函数能够实现 两个数字的求和 功能
代码如下:
def sum_2_num():
num1 = 10
num2 = 20
result = num1 + num2
print("%d + %d = %d" % (num1, num2, num1 + num2))
sum_2_num()
在函数名的后面小括号内部填写 参数
多个参数之间使用 , 分离
def sum_2_num(num1,num2):
result = num1 + num2
print("%d + %d = %d" % (num1, num2, num1 + num2))
sum_2_num(50,20)
函数,把具有独立功能的代码块组织为一个小模块,在需要的时候调用函数的参数、增加函数的通用性,针对 相同的数据处理逻辑、能够适应 更多的数据
1.在函数内部,把参数当做变量使用,进行需要的数据处理
2.函数调用时,按照函数定义的参数顺序、把希望在函数内部处理的数据 通过 参数 传递
形参:定义函数时,小括号中的参数,是用来接收参数用的,在函数内部作为变量使用
实参:调用函数时,小括号中的参数,是用来把数据传递到函数内部用的
一个函数里面又 调用了 另外一个函致,这就是 函数嵌套调用
如果函数 test2 中,调用了另外一个函数 test1
那么执行到调用 test1 函数时,会先把函数test1中的任务都执行完
才会回到 test2 中调用函数 test1 的位置,继续执行后续的代码
def test1():
print("*" * 50)
print("test 1")
print("*" * 50)
def test2():
print("_" * 50)
print("test 2")
test1()
print("_" * 50)
test2()
函数调用自身的编程技巧称为递归
递归函数的特点:
代码特点:
在函数内部定义另一个函数,也就是函数的嵌套
在外部函数的作用域内,外部函数可以随意调用内部函数
由于内部函数的整个定义过程都在外部函数中,所以出了外部函数就无法再被调用了
def outside():
print('外部函数被调用')
def inside():
print('内部函数被调用')
inside()
执行结果
>>>outside()
外部函数被调用
内部函数被调用
>>>inside() NameError: name 'inside' is not defined
内部函数的特点:
1.可以访问外部函数的变量
2.内部函数可以修改外部函数的可变类型的变量 比如:list1
3.函数内部修改全局变量,要加global 变量名,内部函数要使用外部函数的不可变类型的变量的时候要加nonlocal
4.locals() 查看本地变量有哪些,以字典的形式输出
globals() 查看全局变量有哪些,以字典的形式输出()
内部函数案例:
a = 100 # 全局变量 def func(): b = 99 # 内部函数 def inner_func(): nonlocal b global a c = 88 # 尝试修改 b += 1 a += 10 c += 12 # 尝试打印 print(a, b, c) inner_func() print(locals()) print(globals()) func()
如果在一个内部函数里引用了外部函数的变量,此时这个内部函数就被称为闭包
#格式:
def 外部函数():
...
def 内部函数()
...
return 内部函数
集合的定义:
某些指定的对象集在一起就成为一个集合,其中每一个对象叫元素
格式:集合名 = {元素1,元素2,…}
例:my_set = {1, 3, 5}
集合是无序的-> 不支持下标索引
集合是可变的数据类型
集合中的元素是唯一的
集合一般用于元组或者列表中的元素去
定义一个空的集合 my_set = set()
注意: my_set = {} 这样的写法为一个空字典
集合的常见操作:
.add() #增加元素
s1 = set()
s1.add('hello')
s1.add('小猪佩奇')
s1.add('lucy')
print(s1)
.update() #可以添加多个元素
t1 = (‘林志玲’, ‘言承旭’)
s1.update(t1)
print(s1)
s1.add(t1) # t1作为一个元素被添加进集合
print(s1)
.remove() #增加删除元素,如果元素存在则删除,不存在则报错:KeyError:
s1.remove("言承旭")
print(s1)
s1.remove('道明寺')
print(s1)
.pop() #随机删除
s1.pop()
print(s1)
.discard() # 类似remove() 移除不存在的元素的时候会报错
s1.discard("道明寺")
print(s1)
.clear() #清空集合
s1.clear()
print(s1)
集合之差集(-)
.difference()
set1 = {1, 2, 3, 4}
set2 = {3, 4, 5, 6}
new_set = set1 - set2
new_set1 = set2 - set1
print(new_set)
print(new_set1)
new_set = set1.difference(set2)
new_set1 = set2.difference(set1)
print(new_set)
print(new_set1)
集合之交集( & )
.intersection()
set1 = {1, 2, 3, 4}
set2 = {3, 4, 5, 6}
new_set = set1 & set2
print(new_set)
set1 = {1, 2, 3, 4}
set2 = {3, 4, 5, 6}
# new_set = set1.intersection(set2)
new_set = set2.intersection(set1)
print(new_set)
集合之并集( | )
.union()
set1 = {1, 2, 3, 4}
set2 = {3, 4, 5, 6}
new_set = set1 | set2
print(new_set)
set1 = {1, 2, 3, 4}
set2 = {3, 4, 5, 6}
new_set = set1.union(set2)
print(new_set)
集合之对称差集(^)
在前一个集合或后一个集合中但不会同时出现在二者中
.symmetric_difference()
set1 = {1, 2, 3, 4}
set2 = {3, 4, 5, 6}
#new_set = (set1 | set2) - (set1 & set2)
new_set = set1 ^ set2
print(new_set)
# new_set = set1.symmetric_difference(set2)
new_set = set2.symmetric_difference(set1)
print(new_set)
不可变类型,内存中的数据不允许被修改:
数字类型 int bool float,complex,long(2.x)
字符串 str
元组 tuple
可变类型,内存中的数据可以被修改
列表 list
字典 dict
集合/frozenset()除外,frozenset() 返回一个冻结的集合,冻结后集合不能再添加或删除任何元素
案例演示:
列表
a = [1, 2, 3]
print(id(a))
a.append(999)
print(a)
print(id(a))
a.remove(2)
print(a)
print(id(a))
a.clear()
print(a)
print(id(a))
字典
d = {"name": "xiaoming"}
print(id(d))
d["age"] = 20
print(d)
print(id(d))
d.pop("age")
print(d)
print(id(d))
d.clear()
print(d)
print(id(d))
注意:
可变类型的数据变化,是通过方法来实现的
如果给一个可变类型的变量,赋值了一个新的数据,引用会被修改
变量不再对之前的数据引用
变量改为对新赋值的数据引用
字典的 key 只能使用不可变类型的数据
d = {"name": "小明"}
d[1] = "整数"
d[(2,)] = "元组"
print(d)
运行结果:
{'name':'小明',1:'整数',(2,):'元组'}
数据类型转换
str() - int() list() set() tuple()
str() - int() list() set() tuple()
list() - set() tuple() dict() # 转换成字典,元素要有固定的格式
dict() - list() # 只能保存字典的键
面对对象(OOP)基本概念
把数据及对数据的操作方法放在一起,作为一个相互依存的整体——对象。对同类对象抽象出其共性,形成类。
面向过程和面向对象,是两种不同的编码方式
过程和函数
面向过程–怎么做
特点
面向对象–谁来做
特点
类
类和对象 是 面向对象编程的两个核心概念
类是对一群具有相同特征或者行为 的事物的一个统称,是抽象的,不能直接使用
特征 被称为属性
行为 被称为方法
对象
对象 是 由类创建出来的一个具体存在,可以直接使用
由哪一个类创建出来的 对象,就拥有在哪一个类 中定义的:属性、方法
对象就是相当于用图纸制造的飞机
在程序开发中,应该先有类,再有对象
类和对象的关系
类的设计
在程序开发中,要设计一个类,通常需要满足三个要素:
1.类名 这类事物的名字,满足大驼峰命名法
2.属性 这类事物具有什么样的特征
3.方法 这类事物具有什么样的行为
大驼峰命名法
CapWords
1.每一个单词的首字母大写
2.单词与单词之间没有 下划线
定义简单的类(只包含方法)
面向对象是更大的封装, 在一个类中封装多个方法, 这样通过这个类创建出来的对象,就可以直接调用这些方法了!
定义只包含方法的类:


案例演示
需求:小猫爱吃鱼
class Cat: """这是一个猫类""" def eat(self): print("小猫爱吃鱼") def drink(self): print("小猫在喝水") # 创建猫对象 tom = Cat() tom.eat() tom.drink() print(tom) 结果输出 小猫爱吃鱼 小猫在喝水 <__mian__.Cat.object at 0x000001ccc70AE1D0>
初始化方法
当使用类名( ) 创建对象时,会自动执行以下操作
1.为对象在内存中分配空间一一创建对象--- __new__
2.为对象的属性设置初始值一一初始化方法(__init__)
这个 初始化方法 就是__init__方法, __init__是对象的内置方法
__init__方法是 专门 用来定义ー个类 具有 哪些属性的方法!
在初始化方法内部定义属性
在__init__方法内部使用 self.属性名=属性的初始值 就可以 定义属性
定义属性之后,再使用 Cat 类创建的对象,都会拥有该属性
class Cat:
"""这是一个猫类"""
def __init__(self):
print("初始化方法")
# 定义用 Cat 类创建的猫对象都有一个 name 的属性
self.name = "Tom"
def eat(self):
print("%s爱吃鱼" % self.name)
# 使用类名() 创建对象的时候,会自动调用初始化方法 __init__
tom = Cat()
tom.eat()
私有属性和方法
在实际开发中,对象的某些属性或方法可能只希望在对象的内部被使用,而不希望在外部被访问到
私有属性就是对象不希望公开的属性
私有方法就是对象不希望公开的方法
定义方式
在定义属性或方法时,在属性名或者方法名前增加两个下划线,定义的就是私有属性或方法
私有属性在外界不能被直接访问
class Girl: def __init__(self, name): self.name = name self.__age = 18 # 将 age 设置成私有属性 def secret(self): print("{}的年龄是{}岁".format(self.name, self.__age)) Anna = Girl("小美") Anna.secret() print(Anna) # 私有属性,不能被外界访问! print(Anna.__age) 程序运行结果: AttributeError: 'Girl' object has no attribute '__age'
私有方法在外界也不能直接调用
面对对象三大特性
1.封装根据职责将属性和方法封装到一个抽象的 类中
2.继承实现代码的重用,相同的代码不需要重复的编写
3.多态不同的对象调用相同的方法,产生不同的执行结果,增加代码的灵活度
继承的概念:子类拥有父类的所有方法和属性
继承的语法:
class 子类名(父类名):
pass
子类继承自父类,可以直接享受父类中已经封装好的方法,不需要再次开发
子类中应该根据职责,封装子类特有的属性和方法
继承的传递性
C类从B类继承,B类又从A 类继承
那么C类就具有B类和A 类的所有属性和方法
子类拥有父类以及父类的父类中封装的所有属性 和方法
子类拥有父类的所有方法和属性
子类继承自父类,可以直接享受父类中已经封装好的方法,不需要再次开发
当父类的方法实现不能满足子类需求时,可以对方法进行重写(override)
重写 父类方法有两种情况
- 覆盖父类的方法
- 对父类方法进行扩展
覆盖父类的方法:
重写之后,在运行时,只会调用子类中重写的方法,而不再会调用父类封装的方法
对父类方法进行扩展
如果在开发中,子类的方法实现中包含父类的方法实现
父类原本封装的方法实现是子类方法的一部分
就可以使用扩展的方式
在子类中重写父类的方法
在需要的位置使用 super( ).父类方法 来调用父类方法的执行
代码其他的位置针对子类的需求,编写子类特有的代码实现
关于 super
在python 中 super 是一个 特殊的类
super( )就是使用 super 类创建出来的对象
最常使用的场景就是在重写父类的方法时,调用 在父类中封装的方法实现
异常的概念
程序在运行时,如果Python解释器遇到一个错误,会停止程序的执行,并且提示一些错误信息。这就是异常
程序停止执行并且提示错误信息这个动作,我们通常称之为:抛出(raise)异常
异常捕获 – 简单的捕获异常语法
程序在运行时,如果对某些代码的执行不能确定是否正确,可以增加try来捕获异常
捕获异常最简单的语法格式:

错误类型捕获
在程序执行时,可能会遇到不同类型的异常,并且需要针对不同类型的异常,做出不同的响应,这个时候,就需要捕获错误类型了
语法如下:

当 Python 解释器 抛出异常 时,最后一行错误信息的第一个单词,就是错误类型
捕获错误未知
在开发时,要预判到所有可能出现的错误,还是有一定难度的
如果希望程序无论出现任何错误,都不会因为 Python 解释器抛出异常而被终止,可以增加一个except
语法如下:
except Exception as result:
print("未知错误%s" % result)
异常捕获完整语法

异常的传递
多继承:子类可以拥有多个父类,并且具有所有父类的属性和方法
class Base1: def demo1(self): print("Base1 的方法") class Bass2: def demo2(self): print("Base2 的方法") class Derived(Base1, Bass2): def test(self): self.demo1() self.demo2() test = Derived() test.demo1() test.demo2()
开发时,应该尽量避免这种容易产生混淆的情况!——如果父类之间存在同名的属性或者方法,应该尽量避免使用多继承
1.封装根据职责将属性和方法封装到一个抽象的 类 中
定义类的准则
2.继承 实现代码的重用,相同的代码不需要重复的编写
设计类的技巧
子类针对自己特有的需求,编写特定的代码
3.多态不同的子类对象,调用相同的父类方法,产生 不同的执行结果
多态可以增加代码的灵活度
以继承和重写父类方法为前提
是调用方法的技巧,不会影响到类的内部设计
类的结构
术语–实例
通常也会把:
1.创建出来的对象叫做类的实例
2.创建对象的动作叫做实例化
3.对象的属性叫做实例属性
4.对象调用的方法叫做实例方法
在程序执行时
对象各自拥有自己的实例属性
调用对象方法,可以通过 self
访问自己的属性
调用自己的方法
结论
每一个对象,都有自己独立的内存空间,保存各自不同的属性
对象的方法,在内存中只有一份,在调用方法时,需要把对象的引用,传递到方法内部
类属性和实例属性
类属性就是给类对象中定义的属性
通常用来记录与这个类相关的特征
类属性不会用于记录具体对象的特征

如果使用 对象.类属性 = 值 赋值语句,只会给对象添加一个属性,而不会影响到类属性的值
语法如下

类方法需要用修饰器 @classmethod 来标识,告诉解释器这是一个类方法
类方法的第一个参数应该是 cls
由哪一个类调用的方法,方法内的cls就是哪一个类的引用
这个参数和实例方法的第一个参数和self 类似
提示:使用其他名称也可以,不过习惯使用 cls
通过类名,调用类方法,调用方法时,不需要传递 cls 参数
在方法内部
可以通过cls访问类的属性
也可以通过cls 调用其他的类方法
静态方法
语法如下:

单例 设计模式
设计模式
设计模式是前人工作的总结和提炼,通常,被人们广泛流传的设计都是针对某一特定问题的成熟的方案
使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性
单例设计模式
目的 — 让类创建的对象,在系统中只有唯一的一个实例
每一次执行类名( ) 返回的对象,内存地址是相同的
单例设计模式的应用场景
音乐播放 对象
回收站 对象
打印机 对象
……
new 方法
重写 new 方法的代码非常固定!
重写 new 方法 一定要return super( ).new(cls)
否则Python的解释器得不到分配了空间的对象引用,就不会调用对象的初始化方法
注意: new 是一个静态方法,在调用时需要主动传递 cls 参数

Python 中的单例
案例
class MusicPlayer(object)
pass
player1 = MusicPlayer()
print(player1)
player2 = MusicPlayer()
print(player2)
程序运行结果
<__main__.MusicPlayer object at 0x00A0E6B8>
<__main__.MusicPlayer object at 0x00A0EC10>
只执行一次初始化工作
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。