函数
二、向函数传递信息
2. 传递列表
在函数中对列表所作的任何修改都是永久性的。如果想禁止函数修改列表,可以向函数传递列表的副本而非原件。用切片表示法[:]创建列表副本。
虽然传递副本可以保留原始内容,但除非有充分理由,否则还是应该将原始列表传递给函数,避免花时间和内存创建副本,提高效率。
3. 传递任意数量的实参
有时候不知道需要接受多少个实参,好在Python允许函数从调用语句中收集任意数量的实参。如下列代码所示,形参名*toppings中的星号*让Python创建一个名为toppings的空元祖,并将收到的所有值都封装到这个元组中。
def make_pizza(*toppings):
print(toppings)
make_pizza('pepperoni')
make_pizza('mushrooms', 'green peppers', 'extra cheese')
i. 结合使用位置实参和任意数量实参
如果要让函数接受不同类型的实参,必须在函数定义中将接纳任意数量的实参的形参放在最后。Python辉县匹配位置实参和关键字实参,再将余下实参都收集到最后一个形参中。注意,通用形参名*args,它也收集任意数量的位置实参。
ii. 使用任意数量的关键字实参
有时候需要接受任意数量的实参,但预先不知道传递给函数的会是什么样的信息。在这种情况下,可以将函数编写成能够接受任意数量的键值对——调用语句提供了多少就接受多少。如下例代码,两个星号让Python创建一个名为user_info的空字典,并将收到的所有名称值对都放到这个字典中。
def build_profile(first, last, **user_info):
user_info['first_name'] = first
user_info['last_name'] = last
return user_info
user_profile = build_profile('albert', 'einstein', location = 'princeton', field = 'physics')
print(user_profile)
注意,通用形参名**kwargs,它也收集任意数量的位置实参。
三、将函数存储在模块中
将函数存储在称为模块的独立文件中,再将模块导入到主程序中,可以隐藏程序代码的细节,将重点放在程序的高层逻辑上,可以在众多不同的程序中重用函数。
1. 导入整个模块:要调用被导入模块中的函数,需要指定被导入模块的名称和函数名,并用句点分隔。
2. 导入特定函数,通过用逗号分隔函数名,可以根据需要从模块中导入任意数量的函数。使用这种语法时,调用函数无需使用句点。
3. 使用as给函数指定别名。
4. 使用as给模块指定别名。
5. 导入模块中的所有函数。使用星号运算符可以让Python导入模块中的所有函数。
#导入整个模块
import pizza #(pizza为一个.py文件)
#导入特定函数
from module_name import function_0, function_1, function_2
#给函数指定别名
from module_name import function_name as fn
#给模块指定别名
import module_name as mn
#导入所有函数
from module_name import *
类
面向对象编程中,编写表示现实世界中的事物或情景的类,并基于这些类来创建对象。根据类来创建对象称为实例化,这让人能够使用类的实例。
一、创建和使用类
根据约定,在Python中,首字母大写的名称指的是类。
class Dog:
def __init__(self, name, age):
"""初始化属性name和age"""
self.name = name
self.age = age
def sit(self):
"""模拟小狗收到命令时蹲下"""
print(f"{self.name} is now sitting")
def roll_over(self):
"""模拟小狗收到命令时打滚"""
print(f"{self.name} rolled over")
1. __init__()
这是一个特殊方法,每根据Dog类创建新实例时,Python就会自动运行它。形参self在这个方法中必不可少,且必须位于其他形参的前面。Python调用这个方法来创建Dog实例时,将自动传入实参self,是一个指向实例本身的引用,让实例可以访问类中的属性和方法。以self为前缀的变量可供类中所有方法使用。
self.name = name 获取与形参name相关联的值,并将其赋给变量name,该变量被关联到当前创建的实例。像这样可通过实例访问的变量称为属性。
2. sit() & roll_over()
这两个方法执行时不需要额外信息,因此之后形参self。
3. 根据类创建实例
my_dog = Dog('Willie', 6)
print(f"My dog's name is {my_dog.name}.")
print(f"My dog's age is {my_dog.age}.")
my_dog.sit()
my_dog.roll_over()
根据Dog类创建实例时,只需给除self外的形参提供值。访问实例的属性,可以使用句点表示法。调用类中的方法时,也使用句点表示法。
二、使用类和实例
1. 给属性指定默认值
直接在__init__()中创建属性并指定默认值即可。
class Car:
def __init__(self, make, model, year):
self.make = make
self.model = model
self.year = year
self.odometer_reading = 0
2. 修改属性的值
i. 直接修改属性的值:创建实例后,直接访问属性修改属性值。
ii. 通过方法修改属性的值:在类中声明一个方法,调用方法即可改变属性值。
三、继承
编写类时,如果要编写的类是另一个类的特殊版本,可以使用继承。原有的类称为父类,新的类是子类。子类继承了父类的所有属性和方法,同时还可以定义自己的属性和方法。
1. 子类的方法__init__()
定义子类时,必须在圆括号内指定父类的名称,__init__()方法接收创建父类实例所需要的信息。super()函数可以调用父类的方法,在下面的例子中,这行代码让Python调用Car类的方法__init__(),让ElectricCar实例包含这个方法中定义的所有属性。
class ElectricCar(Car):
def __init__(self, make, model, year):
super.__init__(make, model, year)
2. 给子类定义属性和方法
在子类中,需要先初始化父类的属性,再初始化子类特有的属性。
3. 重写父类的方法
父类的方法中,只要不符合子类模拟的实物的行为,都可以进行重写,只需要在子类中定义一个和要重写的父类的方法同名的方法,这样,Python不会考虑父类方法,而只关注子类方法。
4. 将实例用作属性