前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >入门必备!面向对象编程之Python函数与类

入门必备!面向对象编程之Python函数与类

作者头像
数据STUDIO
发布2021-06-24 14:28:57
7430
发布2021-06-24 14:28:57
举报
文章被收录于专栏:数据STUDIO

Python支持大多数面向对象编程技术。在Python中所有东西都是对象,包括类、函数、数和模块。它允许多态性,不只是在类层级之内而且通过采用鸭子类型的方式。任何对象可以用于任何类型,只要它有适当的方法和特性就能工作。

Python的函数支持递归和闭包及其他头等函数特征,但不支持函数重载。Python的函数作为第一类对象,具有和普通对象平等的地位。

本文继续总结Python基础中的重要部分--函数与类。

函数

函数用于完成一项特定的工作。函数允许您只编写一次代码,然后在需要完成相同任务时运行这些代码。函数可以接收它们需要的信息,并返回它们生成的信息。有效地使用函数可以使程序更容易编写、读取、测试和修复。

函数定义

函数的第一行是它的定义,用关键字def标记。函数名后面跟着一组圆括号和冒号。用三引号括起来的文档字符串描述函数的功能。函数体缩进一层。要调用一个函数,请在函数名之后加上一组圆括号。

我们可以自己定义一个函数,但是需要遵循以下的规则:

  • 函数的代码块以def关键字开头,后接函数名称和圆括号()
  • 圆括号用来存储要传入的参数和变量,这个参数可以是默认的也可以是自定义的。
  • 函数内容以冒号起始,并且有强制缩进。
  • return 结束函数。选择性的返回一个值给对方调用。不带表达式的return相当于返回 None。
代码语言:javascript
复制
def greet_user():
    """Display a simple greeting."""
    print("Hello!")
greet_user()

传入一个参数

代码语言:javascript
复制
def greet_user(username):
    """Display a personalized greeting."""
    print("Hello, " + username + "!")
greet_user('jesse')
greet_user('diana')
greet_user('brandon')

位置参数和关键参数

两种主要的参数是位置参数和关键字参数。

使用位置参数时,Python将函数调用中的第一个参数与函数定义中的第一个形参进行匹配,依此类推。

使用关键字参数,您可以指定每个参数应该在函数调用中赋值给哪个形参。当您使用关键字参数时,参数的顺序并不重要。

  • 位置参数
代码语言:javascript
复制
def describe_pet(animal, name):
    """Display information about a pet."""
    print("\nI have a " + animal + ".")
    print("Its name is " + name + ".")
    
describe_pet('hamster', 'harry')
describe_pet('dog', 'willie')
  • 关键参数
代码语言:javascript
复制
def describe_pet(animal, name):
    """Display information about a pet."""
    print("\nI have a " + animal + ".")
    print("Its name is " + name + ".")
describe_pet(animal='hamster', name='harry')
describe_pet(name='willie', animal='dog')

默认参数

可以为参数提供默认值。当函数调用忽略此实参时,将使用默认值。在函数定义中,带有默认值的形参必须列在没有默认值的形参之后,这样位置实参仍然可以正常起作用。

  • 使用默认值
代码语言:javascript
复制
def describe_pet(name, animal='dog'):
    """Display information about a pet."""
    print("\nI have a " + animal + ".")
    print("Its name is " + name + ".")
describe_pet('harry', 'hamster')
describe_pet('willie')
  • 使用None语使参数可选
代码语言:javascript
复制
def describe_pet(animal, name=None):
    """Display information about a pet."""
    print("\nI have a " + animal + ".")
    if name:
        print("Its name is " + name + ".")
describe_pet('hamster', 'harry')
describe_pet('snake')

返回值

函数可以返回一个值或一组值。当函数返回值时,调用行必须提供一个用于存储返回值的变量。函数在到达return语句时停止运行。

  • 返回单个值
代码语言:javascript
复制
def get_full_name(first, last):
    """Return a neatly formatted full name."""
    full_name = first + ' ' + last
    return full_name.title()
musician = get_full_name('jimi', 'hendrix')
print(musician)
  • 返回一个字典
代码语言:javascript
复制
def build_person(first, last):
    """Return a dictionary of information
    about a person.
    """
    person = {'first': first, 'last': last}
    return person
musician = build_person('jimi', 'hendrix')
print(musician)
  • 返回一个包含可选值的字典
代码语言:javascript
复制
def build_person(first, last, age=None):
    """Return a dictionary of information
    about a person.
    """
    person = {'first': first, 'last': last}
    if age:
        person['age'] = age
    return person
musician = build_person('jimi', 'hendrix', 27)
print(musician)
musician = build_person('janis', 'joplin')
print(musician)

将列表传递给函数

您可以将列表作为参数传递给函数,函数可以使用列表中的值。该函数对列表所做的任何更改都将影响原始列表。你可以通过传递列表的副本作为参数来阻止函数修改列表。

  • 将列表作为参数传递
代码语言:javascript
复制
def greet_users(names):
    """Print a simple greeting to everyone."""
    for name in names:
        msg = "Hello, " + name + "!"
        print(msg)
usernames = ['hannah', 'ty', 'margot']
greet_users(usernames)
  • 允许函数修改列表

下面的示例将模型列表发送到一个函数以进行打印。原始列表被清空,第二个列表被填充。

代码语言:javascript
复制
def print_models(unprinted, printed):
    """3d print a set of models."""
    while unprinted:
        current_model = unprinted.pop()
        print("Printing " + current_model)
        printed.append(current_model)
        
# 存储一些未打印的设计,并打印每一个。
unprinted = ['phone case', 'pendant', 'ring']
printed = []
print_models(unprinted, printed)
print("\nUnprinted:", unprinted)
print("Printed:", printed)
  • 阻止函数修改列表

下面的示例与前面的示例相同,只是在调用print_models()之后原始列表没有改变。

代码语言:javascript
复制
def print_models(unprinted, printed):
    """3d print a set of models."""
    while unprinted:
        current_model = unprinted.pop()
        print("Printing " + current_model)
        printed.append(current_model)

# 存储一些未打印的设计,并打印每一个。
original = ['phone case', 'pendant', 'ring']
printed = []
print_models(original[:], printed)  
print("\nOriginal:", original)
print("Printed:", printed)

传入任意数量的参数

有时你不知道一个函数需要接受多少参数。

Python允许您使用*操作符将任意数量的参数收集到一个形参中。接受任意数目实参的形参必须出现在函数定义的最后。

**操作符允许参数收集任意数量的关键字参数。

  • 收集任意数量的参数
代码语言:javascript
复制
def make_pizza(size, *toppings):
    """Make a pizza."""
    print("\nMaking a " + size + " pizza.")
    print("Toppings:")
    for topping in toppings:
        print("- " + topping)
        
# 用不同的配料做三个披萨。
make_pizza('small', 'pepperoni')
make_pizza('large', 'bacon bits', 'pineapple')
make_pizza('medium', 'mushrooms', 'peppers',
           'onions', 'extra cheese')
  • 收集任意数量的关键字参数
代码语言:javascript
复制
def build_profile(first, last, **user_info): 
   """Build a user's profile dictionary.""" 
   # 使用所需的键构建字典。
   profile = {'first': first, 'last': last}
    # 添加任何其他键和值。
    for key, value in user_info.items():
        profile[key] = value
    return profile

# 创建两个具有不同类型信息的用户。
user_0 = build_profile('albert', 'einstein',
                       location='princeton')
user_1 = build_profile('marie', 'curie',
                       location='paris', 
                       field='chemistry')
print(user_0)
print(user_1)

模块

可以将函数存储在名为模块的单独文件中,然后将所需的函数导入包含主程序的文件中。这允许更纯粹的程序文件。(确保模块与主程序存储在同一个目录中。)

  • 在模块中存储函数 文件:pizza.py
代码语言:javascript
复制
def make_pizza(size, *toppings):
    """Make a pizza."""
    print("\nMaking a " + size + " pizza.")
    print("Toppings:")
    for topping in toppings:
        print("- " + topping)
  • 导入整个模块 文件:making_pizzas.py 模块中的每个函数都可以在程序文件中找到。
代码语言:javascript
复制
import pizza
pizza.make_pizza('medium', 'pepperoni')
pizza.make_pizza('small', 'bacon', 'pineapple')
  • 导入特定函数 程序文件中只有导入的函数可用。
代码语言:javascript
复制
from pizza import make_pizza
make_pizza('medium', 'pepperoni')
make_pizza('small', 'bacon', 'pineapple')
  • 给一个模块一个别名
代码语言:javascript
复制
import pizza as p
p.make_pizza('medium', 'pepperoni')
p.make_pizza('small', 'bacon', 'pineapple')
  • 给一个函数一个别名
代码语言:javascript
复制
from pizza import make_pizza as mp
mp('medium', 'pepperoni')
mp('small', 'bacon', 'pineapple')
  • 从模块中导入所有函数

最好不要这样做,但当你在别人的代码中看到它时要认出它。它可能会导致命名冲突,从而导致错误。

代码语言:javascript
复制
from pizza import *
make_pizza('medium', 'pepperoni')
make_pizza('small', 'bacon', 'pineapple')

类定义对象的行为和对象可以存储的信息类型。类中的信息存储在属性中,属于类的函数称为方法。子类继承其父类的属性和方法。

类是面向对象编程的基础。类表示希望在程序中建模的真实世界的事物:例如,狗、汽车和机器人。可以使用一个类来创建对象,这些对象是狗、汽车和机器人的特定实例。类定义了整个对象类别可以拥有的一般行为,以及可以与这些对象关联的信息。

类可以相互继承——可以编写一个扩展现有类功能的类。这允许有效地编写各种情况下的代码。

命名约定: 在Python中,类名用驼峰大小写写,对象名用小写下划线写。包含类的模块仍然应该用小写下划线命名。

创建和使用一个类

考虑一下我们如何建模一辆汽车。我们会把什么信息和汽车联系起来,它会有什么行为?信息存储在称为属性的变量中,行为由函数表示。属于类的函数称为方法。

  • 创建一个小狗类
代码语言:javascript
复制
class Dog():
    """Represent a dog."""
    def __init__(self, name):
        """Initialize dog object."""
        self.name = name
        
    def sit(self):
       """Simulate sitting."""
        print(self.name + " is sitting.")
        
my_dog = Dog('Peso')
print(my_dog.name + " is a great dog!")
my_dog.sit()
  • 创建一个车的类
代码语言:javascript
复制
class Car():
    """A simple attempt to model a car."""
    def __init__(self, make, model, year):
        """Initialize car attributes."""
        self.make = make
        self.model = model
        self.year = year
        # 燃料容量和液位(加仑)。
        self.fuel_capacity = 15
        self.fuel_level = 0
    def fill_tank(self):
        """Fill gas tank to capacity."""
        self.fuel_level = self.fuel_capacity
        print("Fuel tank is full.")
    def drive(self):
        """Simulate driving."""
        print("The car is moving.")
  • 从类中创建对象
代码语言:javascript
复制
 my_car = Car('audi', 'a4', 2016)
  • 访问属性值
代码语言:javascript
复制
print(my_car.make)
print(my_car.model)
print(my_car.year)
  • 调用方法
代码语言:javascript
复制
my_car.fill_tank()
my_car.drive()
  • 创建多个对象
代码语言:javascript
复制
my_car = Car('audi', 'a4', 2016)
my_old_car = Car('subaru', 'outback', 2013)
my_truck = Car('toyota', 'tacoma', 2010)

修改属性

可以直接修改属性的值,也可以编写更仔细地管理值更新的方法。

  • 直接修改属性
代码语言:javascript
复制
my_new_car = Car('audi', 'a4', 2016)
my_new_car.fuel_level = 5
  • 编写更新属性值的方法
代码语言:javascript
复制
def update_fuel_level(self, new_level):
    """Update the fuel level."""
    if new_level <= self.fuel_capacity:
        self.fuel_level = new_level
    else:
    print("The tank can't hold that much!")
  • 编写递增属性值的方法
代码语言:javascript
复制
def add_fuel(self, amount):
    """Add fuel to the tank."""
    if (self.fuel_level + amount
            <= self.fuel_capacity):
        self.fuel_level += amount
        print("Added fuel.")
  else:
    print("The tank won't hold that much!")

类继承

如果正在编写的类是另一个类的专门化版本,则可以使用继承。

当一个类从另一个类继承时,它会自动继承父类的所有属性和方法。子类可以自由地引入新的属性和方法,并覆盖父类的属性和方法。

要从另一个类继承,在定义新类时将父类的名称包含在括号中。

  • 子类的__init__()方法
代码语言:javascript
复制
# 小狗类的继承
class SARDog(Dog):
    """Represent a search dog."""
    def __init__(self, name):
        """Initialize the sardog."""
        super().__init__(name)
    def search(self):
        """Simulate searching."""
        print(self.name + " is searching.")
my_dog = SARDog('Willie')
print(my_dog.name + " is a search dog.")
my_dog.sit()
my_dog.search()
代码语言:javascript
复制
# 汽车类的继承
class ElectricCar(Car):
    """A simple model of an electric car."""
    def __init__(self, make, model, year):
        """Initialize an electric car."""
        super().__init__(make, model, year)
        # Attributes specific to electric cars.
        # Battery capacity in kWh.
        self.battery_size = 70
        # Charge level in %.
        self.charge_level = 0
  • 向子类添加新方法
代码语言:javascript
复制
class ElectricCar(Car):
    --snip--
    def charge(self):
        """Fully charge the vehicle."""
        self.charge_level = 100
        print("The vehicle is fully charged.")
  • 使用子类方法和父类方法
代码语言:javascript
复制
my_ecar = ElectricCar('tesla', 'model s', 2016)
my_ecar.charge()
my_ecar.drive()
  • 重写父类方法
代码语言:javascript
复制
class ElectricCar(Car):
    --snip--
    def fill_tank(self):
        """Display an error message."""
        print("This car has no fuel tank!")

实例属性

一个类可以以对象作为属性。这允许类一起工作来建立复杂的情况。

  • 一个电池类
代码语言:javascript
复制
class Battery():
    """A battery for an electric car."""
    def __init__(self, size=70):
        """Initialize battery attributes."""
        # 容量以千瓦时计,充电水平以%计。
        self.size = size
        self.charge_level = 0
    def get_range(self):
        """Return the battery's range."""
        if self.size == 70:
            return 240
        elif self.size == 85:
      return 270
  • 使用实例作为属性
代码语言:javascript
复制
class ElectricCar(Car):
    --snip--
    def __init__(self, make, model, year):
        """Initialize an electric car."""
        super().__init__(make, model, year)
        # 属性是电动汽车。
        self.battery = Battery()
    def charge(self):
        """Fully charge the vehicle."""
        self.battery.charge_level = 100
        print("The vehicle is fully charged.")
  • 使用实例
代码语言:javascript
复制
my_ecar = ElectricCar('tesla', 'model x', 2016)
my_ecar.charge()
print(my_ecar.battery.get_range())
my_ecar.drive()

导入类

只要添加了详细的信息和功能,类文件就会变得很长。为了帮助保持程序文件整洁,可以将类存储在模块中,并将所需的类导入到主程序中。

  • 在文件中存储类 car.py
代码语言:javascript
复制
"""Represent gas and electric cars."""
class Car():
    """A simple attempt to model a car."""
    --snip--
class Battery():
    """A battery for an electric car."""
    --snip--
class ElectricCar(Car):
    """A simple model of an electric car."""
    --snip--
  • 从模块中导入单个类 my_cars.py
代码语言:javascript
复制
from car import Car, ElectricCar
my_beetle = Car('volkswagen', 'beetle', 2016)
my_beetle.fill_tank()
my_beetle.drive()
my_tesla = ElectricCar('tesla', 'model s', 2016)
my_tesla.charge()
my_tesla.drive()
  • 导入整个模块
代码语言:javascript
复制
import car
my_beetle = car.Car(
        'volkswagen', 'beetle', 2016)
my_beetle.fill_tank()
my_beetle.drive()
my_tesla = car.ElectricCar(
        'tesla', 'model s', 2016)
my_tesla.charge()
my_tesla.drive()
  • 从模块中导入所有类
代码语言:javascript
复制
from car import *
my_beetle = Car('volkswagen', 'beetle', 2016)
  • 在列表中存储对象

一个列表可以包含任意多的项,因此可以从一个类中创建大量对象并将它们存储在一个列表中。

下面是一个示例,演示如何创建一个出租车队,并确保所有的汽车都已准备就绪。

代码语言:javascript
复制
from car import Car, ElectricCar
# 列出一个车队的名单。
gas_fleet = []
electric_fleet = []
# 生产500辆汽油车和250辆电动汽车。
for _ in range(500):
    car = Car('ford', 'focus', 2016)
    gas_fleet.append(car)
for _ in range(250):
    ecar = ElectricCar('nissan', 'leaf', 2016)
    electric_fleet.append(ecar)
# 给汽车加油,给电动汽车充电。
for car in gas_fleet:
    car.fill_tank()
for ecar in electric_fleet:
    ecar.charge()
print("Gas cars:", len(gas_fleet))
print("Electric cars:", len(electric_fleet))
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-05-02,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 数据STUDIO 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 函数
    • 函数定义
      • 传入一个参数
        • 位置参数和关键参数
          • 默认参数
            • 返回值
              • 将列表传递给函数
                • 传入任意数量的参数
                  • 模块
                    • 创建和使用一个类
                      • 修改属性
                        • 类继承
                          • 实例属性
                            • 导入类
                            相关产品与服务
                            对象存储
                            对象存储(Cloud Object Storage,COS)是由腾讯云推出的无目录层次结构、无数据格式限制,可容纳海量数据且支持 HTTP/HTTPS 协议访问的分布式存储服务。腾讯云 COS 的存储桶空间无容量上限,无需分区管理,适用于 CDN 数据分发、数据万象处理或大数据计算与分析的数据湖等多种场景。
                            领券
                            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档