第8章 函数
8.1 定义函数
函数就是执行特定任务的一段代码, 自定义函数的语法格式, 以英文半角冒号结尾. # def:
8.2 调用函数
在定义好函数后,既可调用函数.
8.2.1 使用位置参数调用函数
在调用函数时传递的实参与定义函数时的形参顺序一致,这是调用函数的基本形式。 # 根据形参对应的位置进行实参传递.
8.2.2 使用关键字参数调用函数
- 在调用函数时可以采用“关键字=实参”的形式,其中,关键字的名称就是定义函数时形参的名称。 # 根据形参名称进行实参传递
- 形参和实参的名称可以不同。 # 关键字实参为对函数变量直接赋值
- 在函数的形参前面加上“*”,则只能采用关键字形参。
8.2.3 参数的传递
- 如果是不可变对象,在函数体的修改不会影响实参的值。
- 如果是可变对象,在函数体的修改会影响到实参的值, # 比如:集合、列表、字典等
8.2.4 函数的返回值
- 如果函数没有返回值 , return可以不写。
- 函数的返回值,如果只有一个,直接返回类型。
- 如果返回值是多个,返回结果为元组。
8.3 参数的默认值
- 函数定义时,给形参设置默认值,只有与默认值不符的时候才需要传递实参。
- 函数定义语言:def。
8.4 可变参数
8.4.1 基于元组的可变参数
# *可变参数 # *args 不定参数
- 可变参数在函数中被组装成一个元组。 # 一个函数只能定义一个可变参数
8.4.2 基于字典的可变参数
# **可变参数
- 可变参数在函数中被组装成一个字典。 # 在一个函数的定义过程中,既有个数可变的关键字形参,也有个数可变的位置形参时,要求,个数可变的位置形参放在个数可变的关键字形参之前.
8.5 函数中变量的作用域
- 变量可以在模块中创建,作用域(变量的有效范围)是整个模块,被称为全局变量。变量也可以在函数中创建,在默认情况下作用域是整个函数,被称为局部变量。
- 局部变量:在函数内定义并使用的变量,只在函数内部有效,局部变量使用 global 声明,这个变量就会就成全局变量。
- 全局变量:函数体外定义的变量,可作用于函数内外。
8.6 函数类型
Python中的任意一个函数都有数据类型,这种数据类型是function,被称为函数类型。
8.6.1 理解函数类型
- 函数类型的数据与其他类型的数据是一样的,任意类型的数据都可以作为函数返回值使用,还可以作为函数参数使用。因此,一个函数可以作为另一个函数返回值使用,也可以作为另一个函数参数使用。
8.6.2 过滤函数filter
- 在Python中定义了一些用于数据处理的函数,如filter()和map()等。 # 设置条件进行筛选
- filter()函数用于对容器中的元素进行过滤处理。
8.6.3 映射函数map
- map() 函数用于对容器中的元素进行映射(或变换)。 # 例如:我想将列表中的所有元素都乘以2,返回新的列表。
8.7 lambda()函数
- 我们之前学习的函数都是有名称的函数,例如在8.1节定义的rect_area()函数,rect_area就是其函数名。我们也可以定义匿名函数,匿名函数就是没有名称的函数。 # 可以简写函数,不在需要设置 def
- 在Python中使用lambda关键字定义匿名函数。lambda关键字定义的函数也被称为lambda()函数,定义lambda( )函数的语法如下。
- “参数列表”与函数的参数列表是一样的,但不需要用小括号括起来。
# 该函数中 def add( ) 函数被简化为了lambda(). ":'” 冒号前面为变量,后面为计算公式
8.8 choices与sample的区别
- random.sample(population, k) # random.sample([1,2,3,4],k=4)
- choices在抽取随机元素时是包含重复元素的,即:一个元素可能会被抽取多次。 # choices函数中可以设置,参数replace,用来设置是否可以取相同元素:True表示可以取相同数字;False表示不可以取相同数字。默认是True np.random.choice(5, 4, replace=False)
- 反之,在sample中,抽取的元素是不重复的。
- 所以,在抽取元素大于样本集总数时,choices会继续而sample会报错: # choices抽取包含重复元素。
根据字典的值排序:
dict1={'a':2,'e':3,'f':8,'d':4}
list1= sorted(dict1.items(),key=lambda x:x[1])
8.9 find()函数
- 通过find( )函数进行查找字符串的时候,如果字符串中存在所需要查找的字符,则返回字符所在的位置,如果未查找到,则返回 '-1'。
8.10 递归函数
- 如果在一个函数的函数体内调用了该函数本身,这个函数就称为递归函数。 # 如果函数内部存在循环语句,慎用,不好退出
- 递归的组成部分递归调用与递归终止条件。
第9章 类与对象
9.1 面向对象
- 面向对象和面向过程。
- 类的名称(类名),由一个或多个单词组成,每个单词首字母大写,其余小写。 # 类型为:class [种类]
9.2 定义类
- Python中的数据类型都是类,我们可以自定义类,即创建一种新的数据类型。
- 类是多个类似事物组成的群体的统称。能够帮助我们快速理解和判断事物的性质。
9.3 创建对象
类相当于一个模板,依据这样的模板来创建对象,就是类的实例化,所以对象也被称为“实例”。
9.4 类的成员
成员变量也被称为数据成员,保存了类或对象的数据。 # 例如,学生的姓名和学号。构造方法是一种特殊的函数,用于初始化类的成员变量。成员方法是在类中定义的函数。属性是对类进行封装而提供的特殊方法。
类的组成:
- 类属性:直接写在类内部的变量,类中方法外的变量称为类属性,被该类的所有对象所共享。
- 实例方法:在类内部定义的 'def' 为实例方法。
- 类方法:使用@classmethod修饰的方法,使用类名直接访问的方法。 # def 内部,通过装饰器进行装饰
- @classmethod 是一个函数修饰符,它表示接下来的是一个类方法,而对于平常我们见到的则叫做实例方法。 类方法的第一个参数cls,而实例方法的第一个参数是self,表示该类的一个实例。
- 普通对象方法至少需要一个self参数,代表类对象实例。
- 静态方法:使用@staticmethod修饰的主法,使用类名直接访问的方法。 # def 内部
- self.name 称为实体属性,进行了一个赋值的操作,将局部变量的name的值赋给了实体属性。
- 动态绑定属性和方法:
- Python是动态语言,在创建对象之后,可以动态地绑定属性和方法。 # 举例: stu2.show = show show 为类名
9.4.1 实例变量
- 实例变量就是对象个体特有的“数据”,例如狗狗的名称和年龄等。
9.4.2 构造方法
- 类中的__init__()方法是一个非常特殊的方法,用来创建和初始化实例变量,这种方法就是“构造方法”。在定义__init__()方法时,它的第1个参数应该是self,之后的参数用来初始化实例变量。调用构造方法时不需要传入self参数。
9.4.3 实例方法
- 实例方法与实例变量一样,都是某个实例(或对象)个体特有的方法。
- 定义实例方法时,它的第1个参数也应该是self,这会将当前实例与该方法绑定起来,这也说明该方法属于实例。在调用方法时不需要传入self,类似于构造方法。
9.4.4 类变量
- 类变量是属于类的变量,不属于单个对象。
- 例如,有一个Account(银行账户)类,它有三个成员变量:amount(账户金额)、interest_rate (利率)和owner(账户名)。amount和owner对于每一个账户都是不同的,而interest_rate对于所有账户都是相同的。amount和owners是实例变量,interest_rate 是所有账户实例共享的变量,它属于类,被称为“类变量”。
9.4.5 类方法
- 类方法与类变量类似,属于类,不属于个体实例。在定义类方法时,它的第1个参数不是self,而是类本身。
9.5 封装性
- 提高程序的安全性,封装性是面向对象重要的基本特性之一。封装隐藏了对象的内部细节,只保留有限的对外接口,外部调用者不用关心对象的内部细节,使得操作对象变得简单。
9.5.1 私有变量
- Python中的变量是公有的,可以在类的外部访问它们。如果想让它们成为私有变量,则在变量前加上双下画线(__)即可。
9.5.2 私有方法
- 私有方法与私有变量的封装是类似的,在方法前加上双下画线(__)就是私有方法了。
9.5.3 使用属性
- 为了实现对象的封装,在一个类中不应该有公有的成员变量,这些成员变量应该被设计为私有的,然后通过公有的set (赋值)和get(取值)方法访问。
- 在Python中没有专门的修饰符用于属性的私有,如果该属性不希望在类对象外部被访问,前边使用两个“_” 。
- 可以通过 dir 调出其中的数值,一般不这样干: # dir () 函数返回指定对象的所有属性和方法,不带值 , 输出其构造方式
- dir( ) 函数不带参数时,返回当前范围内的变量、方法和定义的类型列表;带参数时,返回参数的属性、方法列表。如果参数包含方法__dir__( ),该方法将被调用。如果参数不包含__dir__( ),该方法将最大限度地收集参数信息。
9.6 继承性
- 继承性也是面向对象重要的基本特性之一。
object类:
- object类是所有类的父类,因此所有类都有object类的属性和方法。
- 内置函数dir( )可以查看指定对象所有属性。
- Object有一个__str__( )方法,用于返回一个对于“对象的描述”,对应于内置函数str( )经常用于print( )方法,帮我们查看对象的信息,所以我们经常会对__str__( )进行重写。
9.6.1 Python中的继承
- 在Python中声明子类继承父类,语法很简单,定义类时在类的后面使用一对小括号指定它的父类就可以了。
9.6.2 多继承
- 在Python中,当子类继承多个父类时,如果在多个父类中有相同的成员方法或成员变量,则子类优先继承左边父类中的成员方法或成员变量,从左到右继承级别从高到低。
- 定义子类时,必须在其构造函数中调用父类的构造函数。
9.6.3 方法重写
- 如果子类的方法名与父类的方法名相同,则在这种情况下,子类的方法会重写(Override)父类的同名方法。
- 如果子类对继承自父类的某个属性子类重写后的方法中可以通过或方法不满意,可以在子类中对其(方法体)进行重新编写。
- super( ).xxx( ) 调用父类中被重写的方法。
9.7 多态性
多态性也是面向对象重要的基本特性之一, “多态”指对象可以表现出多种形态。
9.7.1 继承与多态
- 在多个子类继承父类,并重写父类方法后,这些子类所创建的对象之间就是多态的。这些对象采用不同的方式实现父类方法。
9.7.2 鸭子类型测试与多态
- Python的多态性更加灵活,支持鸭子类型测试。鸭子类型测试指:若看到一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟可以被称为鸭子。
9.8 特殊方法和特殊属性
- 通过super() 调用父类.
9.9 类的浅拷贝与深拷贝
- 变量的赋值操作:只是形成两个变量,实际上还是指向同一个对象 # 类似只拷贝了一个索引,存储地址没变
- 浅拷贝:Python拷贝一般都是浅拷贝,拷贝时,对象包含的子对象内容不拷贝,因此,源对象与拷贝对象会引用同一个子对象.
- 深拷贝:使用copy模块的deepcopy函数,递归拷贝对象中包含的子对象,源对象和拷贝对象所有的子对象也不相同.