函数、类与代码复用
代码复用的思想
把代码当成资源进行抽象。
代码资源化:程序代码是一种用来表达计算的"资源"
代码抽象化:使用函数等方法对代码赋予更高级别的定义
代码复用:同一份代码在需要时可以被重复使用
函数和对象是代码复用的主要形式,对象化的抽象程度更高
模块化设计、分而治之:模块内部紧耦合(交流多、不可独立);模块之间松耦合(交流少、可独立)
函数
函数的定义
函数实例:
def do_something():
"""这是函数注释"""
print("Hello World!")
do_something()
def进行函数定义,接下来是函数名,括号内是参数表,随后是:下一行进行函数体,三对引号是文档注释。像c_like语言一样调用函数
使用参数的函数:
def do_something(name):
"""这是注释"""
print("Hello "+name.title()+"!")
do_something()
这里参数没必要指出类型
传递实参:函数传递实参的方式很多,可使用位置实参,这要求实参顺序与形参顺序对应,也可使用关键字实参,其中每个实参都由变量名和值组成;此外,还可以使用列表和字典。
位置实参:调用函数时,python会将每一个实参都关联到函数定义的一个形参,最简单的关联方式是基于实参的顺序,这种关联方式被称为位置实参
#定义函数
def describe_pet(animal_type, pet_name):
"""显示宠物信息"""
print("\nI have a "+animal_type+" and its name is " + pet_name.title()+".")
#调用函数, 实参按照一定顺序赋值给形参
describe_pet('hamster', 'harry')
describe_pet('dog','pearl')
关键字实参:传递给函数的名称-值对,直接在是惨重将名称和值关联,无所谓顺序
#调用函数,按照关键字传递实参
describe_pet(animal_type='hamster', pet_name='harry')
describe_pet(animal_type='dog',pet_name='pearl')
默认值:在定义函数时,添加默认值,当没有合适的实参传入时,将会使用默认值版本(写法同c++),要求也与c++相同,要求带有默认值的形参放在最后
通过给某个形参赋值空初始值'',可以实现可选参数的功能
返回值:值得注意,python没有必要定义函数时说明有无返回值和返回值类型。返回简单值、字典都可以;返回一个值、多个值、零个值都可以。返回多个值的时候会以元组的方式返回。
~~~ python
def get_formatted_name(first_name,last_name):
full_name= first_name + ' ' + last_name
return full_name.title()
def get_formatted_name_dic(first_name,last_name):
person = {
'first': first_name,
'last': last_name
}
return person
musician = get_formatted_name('zhao','siqi')
print(musician)
~~~
传递列表
def greet_users(names):
"""to greet"""
for name in names:
msg = 'Hello, ' + name.title() + '!'
print(msg)
usernames['A', 'B', 'C']
grret_users(usernames)
在函数中修改列表:列表传递给函数后,函数就可以对其进行修改,在函数中对列表的修改是永久性的
禁止函数修改列表:将列表的副本传递给函数,比如function_name(list_name[:])
传递未定数量的实参:
有时不知道函数需要接受多少实参,于是使用可变形参*或**其中前者创建了一个内容可变的空元组,后者创建了内容可变的空字典
def make_pizza(*topping):
print(toppings)
make_pizza('Chicken')
make_pizza("mushroom", "Chicken", "beef")
这里的*topping创建了一个空元组,并将收到的所有值都封装到元组中
同时使用位置形参和任意数量形参:位置形参应该位于任意数量形参之前
同时使用关键字形参和任意数量形参:一般使用关键字形参和任意数量形参时都使用了空字典
def build_profile(first, last, **user_info):
profile={
'first_name': first,
'last_name': last
}
for key, value in user_info:
profile[key] = value
return profile
user_profile = build_profile('albert','einstein', location = 'German', field = 'physics')
print(user_profile)
将函数储存在模块中
将函数存储在被称为模块的独立文件,再将模块导入(import)到主程序(注:模块也是.py文件)
导入整个模块:
import
随后的调用函数:
modele_name.function_name(...)
导入某个函数
from import,
使用as指定别名
from import as new_name
使用as给模块指定别名
import as
导入模块的所有函数
from module_name import*
调用函数时不必加模块名.
局部变量和全局变量:
(这里局部变量会在离开作用域时自动释放)
基本数据模型,无论是否重名,局部变量与全局变量不同:
即发生了作用域和可视性的覆盖
可以通过global关键字声明全局变量
经过实验,global声明的变量可以在局部作用域内使用、修改,且会修改原始的全局变量。并且在函数内使用global关键字可以创建原来并不存在的全局变量
def func():
global num
num = 9
return num
t = func()
m = num
print(str(t))
print(str(m))
print(str(num))
# 输出
# 9
# 9
# 9
对于组合数据类型,如果局部变量未创建,那么就会使用全局变量
lambda函数:
lambda函数是一种匿名函数,使用Lambda保留字定义,不指定函数名,函数名即为赋值的变量(类似于创建了一个函数指针,将指针赋给了某变量,随后该变量可当作函数名正常使用),一般仅仅定义简单的,能够用一行表示的代码,常常用于大型函数的函数对象使用
# 基本形式
= Lambda :
# 例子
add = Lambda x, y : x+y
函数编写时的注意细节:
命名只使用小写字母和下划线
包含带有对功能简易说明的注释
给形参指定默认值时等号两侧不要加空格
所有import都要放在(除了)注释外的最前面
定义函数的代码块后加两行空行与其他部分分开
函数递归
关键特征:
链条:计算过程中存在递归链条
基例:存在一个或多个不需要再次递归的基例
核心编写方法在于分支语句对参数进行判断,分别处理基例和链条
类和对象
根据约定,在python中,首字母大写的名称指的是类(即是命名规则,也是使用提示)
创建和使用类:
class Dog():
def __init__(self, name, age):
self.name = name
self.age = age
def sit(self):
print(self.name.title() + "is sitting")
类中的函数称为方法,与普通函数的唯一区别在于调用的方式,通过对象.方法名(参数表)的方式调用
__init__()是一种特殊的函数(构造函数),创建实例时自动调用
形参self必不可少,且必须位于其他形参最前面,但是调用时不必传递实参,因为它自动指向实例本身的引用
使用类
# 已经定义好Dog类
#创建实例
my_dog = Dog("A", 3)
#访问属性
print("My dog's name is "+my_dog.name.title())
#调用方法
my_dog.sit()
给属性指定默认值:在构造函数(__init__)指定这种初始值,此时不必在形参表中写出
修改属性的值:
通过访问成员直接修改属性的值
定义成员函数修改属性的值
继承
子类的构造函数
class Dog():
#略
class My_dog(Dog):
def __init__(self, name, age, weight):
super().__init__(name, age)
self.weight = weight
通过super()获取父类的引用,随后借助父类的构造函数完成构造
重写父类的方法:在子类中定义一个与父类中同名的方法,此时会直接调用子类的同名方法
将实例用作属性:使用代码模拟实物时,类中的属性和方法可能会越来越长,此时将类的一部分作为一个独立的类提取出来,将大型类拆分成多个协同工作的小类
导入类:与导入函数的操作基本相同
Python标准库:
Python标准库是一组模块,安装的python都含有它
例题:使用collections的一个类——OrderedDict,这是一个有序字典,在保存键值对关系的同时保留顺序
from collections import OrderedDict
favorite_languages = OrderedDict()
favorite_languages['Jen'] = 'python'
favorite_languages['Sarah'] = 'c'
favorite_languages['edward'] = 'ruby'
favorite_languages['phil'] = 'python'
for name.language in favotite_languages.items():
print(name.title() + "like " + language + ".")
类编码风格
类名实施驼峰命名法,将每个单词的首字母大写,不适用下划线,实例名和模块名使用小写,并在单词之间加下划线。
每个类在定义后使用文档注释描述类功能
在需要同时导入标准库和编写的自定义模板时,先import标准库,空行,再import自定义库