<Python> python从入门到实践(5) --代码复用
函数、类与代码复用
代码复用的思想
- 把代码当成资源进行抽象。
- 代码资源化:程序代码是一种用来表达计算的"资源"
- 代码抽象化:使用函数等方法对代码赋予更高级别的定义
- 代码复用:同一份代码在需要时可以被重复使用
- 函数和对象是代码复用的主要形式,对象化的抽象程度更高
- 模块化设计、分而治之:模块内部紧耦合(交流多、不可独立);模块之间松耦合(交流少、可独立)
函数
函数的定义
- 函数实例:
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<module name>
随后的调用函数:modele_name.function_name(...) -
导入某个函数
from <module_name> import<fuction_name1>, <function_name2> -
使用as指定别名
from <module_name> import<fuction_name1> as new_name -
使用as给模块指定别名
import<modele_name> as <new_name> -
导入模块的所有函数
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自定义库

浙公网安备 33010602011771号