百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

Python实用案例编程入门:第五章 函数和类

off999 2024-09-21 20:49 30 浏览 0 评论

本章的主题为函数和类,在编程中比较重要的概念。

5.1 函数

Python语言提供了函数的概念,就是给代码块赋予一个名字,然后所有需要使用该代码块的地方都直接调用该代码的名字即可,就叫做函数,该名字叫函数名。这样,我们就可以通过函数名来表示该代码块所提供的功能,在任何使用的地方只需要调用该函数名即可,而不用每个使用的地方都重复该代码块。及便于重复使用已有代码,也方便调试和修改,比如我们希望修改该功能块,只需要修改该函数内的代码即可,而无需修改所有的被使用的地方。

同时呢,由于函数的使用,主程序就没有那么多代码,使主程序的结构清晰易于理解。

5.1.1 函数的定义

函数定义时需要指定一个能够描述所要做的事情的名称,Python中约定使用小写字母加下划线的形式,函数的定义如下所示。

def say_hi():
"""say hi"""
	print("你好")

上面的代码片段是一个函数定义的示例,def后面跟着函数名,函数名后面必须是圆括号,圆括号后面是冒号,然后紧跟着函数的代码块。函数名称部分可以自定定义,一般采用小写字母加下划线的方式。在使用函数的时候,可以直接用函数名加圆括号即可。

say_hi()
>>>你好

该函数的定义没有参数,我们可以定义有入参的函数,让函数的功能更灵活。

def say_hi(language):
"""say hi"""
	print("你好 " + language)

say_hi("Python")
say_hi("C++")
>>>你好 Python
>>>你好 C++

从上面的例子可以看出,我们可以通过say_hi()函数去对不同的语言问好,但不需要对每个语言都编写相同的代码块。

函数除了让我们代码块更容易复用之外,也能够让调用函数的主函数更加的简洁,易于阅读和修改。程序的可阅读性是非常重要的,对于编程来说,调试代码花的时间可能更多,但在调试过程中需要清楚的知道程序的逻辑和结构,而函数使代码更具模块话,用一个函数名就代替了一个功能块的好几行代码,甚至几十行,因此函数对于编程来说非常有用。

5.1.2 函数的参数及默认值

如上节所示,函数支持参数传递,这就让函数可以灵活的接收来自调用者传递的数据。

在将列表作为参数有点特殊,函数可以修改列表的内容,从而使用调用者的数据也被修改了。而其他类型的数据,函数仅仅是将数值传递给函数使用,并不会修改调用者持有的数据内容。因此,列表显得比较特殊,但我们也可以将列表作为参数传递给函数,同时也不会修改调用者持有的列表值。列表有一个称之为拷贝的方法,可以将列表的内容复制一份作为参数进行传递,比如list[:]或者copy()方法。

example_language = ['C++', 'Python']

def say_hi(languages):
"""say hi"""
  for language in languages:
  	print("你好 " + language)

languages.append("Java")

say_hi(example_language)
print(example_language)
>>>你好 C++
>>>你好 Python
>>> ['C++', 'Python', 'Java']

有上面的代码我们可以知道,函数say_hi()修改了example_languages的值,而这可能不是我们所期望的。如上面所述,我们可以通过相应的方法来解决该问题。

example_language = ['C++', 'Python']

def say_hi(languages):
"""say hi"""
  languages.append("Java")
  for language in languages:
  	print("你好 " + language)

say_hi(example_language[:])
print(example_language)
>>>你好 C++
>>>你好 Python
>>>你好 Java
>>>['C++', 'Python']

从运行的结果来看,函数并没有修改调用者的数据,而只是函数自己内部的参数值被修改了,再看看另一种方法。

example_language = ['C++', 'Python']
def say_hi(languages):
"""say hi"""
  languages.append("Java")
  for language in languages:
  	print("你好 " + language)

say_hi(example_language.copy())
print(example_language)
>>>你好 C++
>>>你好 Python
>>>你好 Java
>>>['C++', 'Python']

函数也可以接收任意数量的参数,比如像下面代码所示。

def say_hi(*languages):
"""say hi"""
  for language in languages:
  	print("你好 " + language)

say_hi('C++', 'Python')
>>>你好 C++
>>>你好 Python
def say_hi(*languages):
"""say hi"""
  for language in languages:
  print("你好 " + language)

say_hi('C++', 'Python', 'Java')
>>>你好 C++
>>>你好 Python
>>>你好 Java

从上面代码可以看出,无论入参有多少个,函数都可以通过for循环迭代逐个处理。我们再看另一个可以接收任意数量键值对的实现。

接收任意数量的键值对,代码示例如下。

def say_hi(**languages):
"""say hi"""
    for language,author in languages.items():
        print("你好 " + author + " and thanks your " + language)

say_hi(Cplusplus='Bjame Stroustrup', Python='Guido', Java='James')
>>>你好 Bjame Stroustrup and thanks your Cplusplus
>>>你好 Guido and thanks your Python
>>>你好 James and thanks your Java

5.1.3 函数的返回值

函数的调用者可以传递数据给函数,同样函数也可以返回数据给调用者。而返回给调用者的数据,我们称之为返回值,这样函数的功能就很全面了。既可以接受来自调用者的数据,也可以返回数据给调用者,从而完成信息交互。

下面的代码展示了函数如何返回值,及调用者如何获取函数返回值。

def say_hi(**languages):
"""say hi"""
    for language,author in languages.items():
        print("你好 " + author + " and thanks your " + language)

 eturn "say hi to all languages successfully"

value = say_hi(Cplusplus='Bjame Stroustrup', Python='Guido', Java='James')
print(value)
>>>你好 Bjame Stroustrup and thanks your Cplusplus
>>>你好 Guido and thanks your Python
>>>你好 James and thanks your Java
>>>say hi to all languages successfully

如程序执行结果所示,函数成功的执行完后,将一个字符串作为返回值return给调用者,而调用者将该返回值存入一个变量value中。通过print函数进行打印,可以看到我们得到就是say_hi()函数的返回的值。

5.2 类

介绍完函数,我们再看看另一个更高级的内容,类。如我们在函数一节所提到的,类也是另一个将代码进行封装的技术,但类比函数更高级,类可以将数据与函数封装在一起。

5.2.1 类的定义

类是一个面向对象编程的概念,我们的程序需要模拟现实世界。而类就是用来模拟现实对象的技术基础,可以将现实中的所有事务用一个类的表示。在一个类的定义中,我们将其中函数称为方法,而将其中的数据称为属性,通过方法进行获取和修改属性,下面来看看一个简单的类定义。

class FirstClass:
    sex = '女性'

def set_sex(self, value):
    self.sex = value

def get_sex(self):
    return self.sex

在上面的类定义中,用一个变量sex保存性别。同时,定义了两个函数分别用于修改性别和获取性别。但需要注意,类中定义的函数的第一个参数必须为self,而操作具体属性时也必须用self.来进行访问,类似于C++程序中this指针。

5.2.2 类的属性

如上面类的定义中所提及,可以在类定义是定义属性。当然,也可以在类的方法中去通过self定义属性。如下代码片段中,我们在set_sex()的方法中通过self.age定义了一个存储年龄的属性。

class FirstClass:
sex = '女性'

def set_sex(self, sex, age):
self.sex = sex
self.age = age

def get_sex(self):
return self.sex

def get_age(self):
return self.age

有了类的定义,我们试着使用该类,下面的代码中我们定义了类的对象first_obj,然后获取默认性别为女性。紧接着,我们通过方法set_sex()修改了性别和年龄,再通过方法get_sex()和get_age()获取了性别和年龄。

first_obj = FirstClass()
sex_value = first_obj.get_sex()
print(sex_value)
first_obj.set_sex('男性', 23)
sex_value = first_obj.get_sex()
age_value = first_obj.get_age()
print(sex_value, age_value)
>>>女性
>>>男性 23

通过上面的代码,我们可以看到都是在通过类的方法进行访问和修改属性。

5.2.3 类的方法

在面向对象编程中,我们只希望给用户提供必要的访问接口,也就是方法,从而隐藏具体实现和数据。我们还是通过上面的类定义来说明方法的定义和使用,定义了三个方法,set_sex()用于设置性别和年龄,get_sex()用于获取性别,而get_age()用于获取年龄,但如果用户想要单独修改年龄怎么办呢?似乎没有现成的方法,那么我们是否可以将set_sex()修改为只设置性别,再增加一个新方法去专门设置年龄呢?答案是肯定的,我们来看看下面的代码。

class FirstClass:
sex = '女性'
age = 18
def set_sex(self, sex):
self.sex = sex

def set_age(self, age):
self.age = age

def get_sex(self):
return self.sex

def get_age(self):
return self.age

上面的代码我们重新定义之前的类,新增了set_age()方法,从而使类的方法定义更加清晰简单,一个函数只做一件事。

first_obj = FirstClass()
sex_value = first_obj.get_sex()
age_value = first_obj.get_age()
print(sex_value)
first_obj.set_sex('男性')
first_obj.set_age(23)
sex_value = first_obj.get_sex()
age_value = first_obj.get_age()
print(sex_value, age_value)
>>>女性
>>>男性 23

从程序的执行结果来看,我们 并未修改程序的执行效果。

5.3 模块

Python提供了模块的机制,可以让我们将函数或者类单独存入一个Python文件中,从而隐藏具体实现。而使用者无需关注具体实现,只是简单的调用函数或者使用类即可,这样我们就可以将该模块文件共享给其他任何人使用,或者很容易的使用在自己的其他程序中。

我们只需要通过import 相应的模块文件名即可,该文件必须是Python文件,导入时只需要导入文件名,不需要加py文件后缀。

我们这里将前面的函数和类存入一个Python文件中作为模块,然后进行导入使用。

该文件名为try_module.py,其内容如下所示。

class FirstClass:
sex = '女性'
age = 18
def set_sex(self, sex):
self.sex = sex

def set_age(self, age):
self.age = age

def get_sex(self):
return self.sex

def get_age(self):
return self.age

def say_hi(**languages):
"""say hi"""
for language,author in languages.items():
print("你好 " + author + " and thanks your " + language)

return "say hi to all languages successfully"
在我们的程序中只需要import这个文件,便可以使用其中的类及函数。
import try_module

first_obj = try_module.FirstClass()
sex_value = first_obj.get_sex()
age_value = first_obj.get_age()
print(sex_value)
first_obj.set_sex('男性')
first_obj.set_age(23)
sex_value = first_obj.get_sex()
age_value = first_obj.get_age()
print(sex_value, age_value)

value = try_module.say_hi(Cplusplus='Bjame Stroustrup', Python='Guido', Java='James')
print(value)

程序执行效果如下,和不用模块时完全一样,但这里简化了程序实现,其他使用者同样只需要导入该模块文件即可。

>>>女性
>>>男性 23
>>>你好 Bjame Stroustrup and thanks your Cplusplus
>>>你好 Guido and thanks your Python
>>>你好 James and thanks your Java
>>>say hi to all languages successfully

除了直接使用import导入所有的内容,还可以通过from try_module import say_hi只导入函数say_hi()。也可以用import try_module as td给模块一个别名,或者通过from try_module import *导入所有的内容,但使用时不需要在前面加模块名。

这里给一段代码示例。

from try_module import say_hi

value = say_hi(Cplusplus='Bjame Stroustrup', Python='Guido', Java='James')
print(value)

import try_module as td

first_obj = td.FirstClass()
sex_value = first_obj.get_sex()
age_value = first_obj.get_age()
print(sex_value)
first_obj.set_sex('男性')
first_obj.set_age(23)
sex_value = first_obj.get_sex()
age_value = first_obj.get_age()
print(sex_value, age_value)

5.4 本章小结

本章我们学习了如何编写函数,将代码块以函数的形式进行定义和使用。同时也介绍了如何定义类,以及类的属性的定义,类的方法的定义及使用,从而让我们有多种手段进行代码封装和更好的复用。

最后介绍了一个Python中比较中的概念,模块。通过模块我们可以将类和函数通过文件进行管理及复用,从而便于使用。模块是Python的一个非常重要的概念,这里仅做了简单的介绍,读者可以通过其他相关资料进行学习理解。

相关推荐

Alist 玩家请进:一键部署全新分支 Openlist,看看香不香!

Openlist(其前身是鼎鼎大名的Alist)是一款功能强大的开源文件列表程序。它能像“万能钥匙”一样,解锁并聚合你散落在各处的云盘资源——无论是阿里云盘、百度网盘、GoogleDrive还是...

白嫖SSL证书还自动续签?这个开源工具让我告别手动部署

你还在手动部署SSL证书?你是不是也遇到过这些问题:每3个月续一次Let'sEncrypt证书,忘了就翻车;手动配置Nginx,重启服务,搞一次SSL得花一下午;付费证书太贵,...

Docker Compose:让多容器应用一键起飞

CDockerCompose:让多容器应用一键起飞"曾经我也是一个手动启动容器的少年,直到我的膝盖中了一箭。"——某位忘记--link参数的运维工程师引言:容器化的烦恼与...

申请免费的SSL证书,到期一键续签

大家好,我是小悟。最近帮朋友配置网站HTTPS时发现,还有人对宝塔面板的SSL证书功能还不太熟悉。其实宝塔早就内置了免费的Let'sEncrypt证书申请和一键续签功能,操作简单到连新手都能...

飞牛NAS部署TVGate Docker项目,实现内网一键转发、代理、jx

前面分享了两期TVGate:Q大的转发代理工具TVGate升级了,操作更便捷,增加了新的功能跨平台内网转发神器TVGate部署与使用初体验现在项目已经开源,并支持Docker部署,本文介绍如何通...

Docker Compose 编排实战:一键部署多容器应用!

当项目变得越来越复杂,一个服务已经无法满足需求时,你可能需要同时部署数据库、后端服务、前端网页、缓存组件……这时,如果还一个一个手动dockerrun,简直是灾难这就是DockerCompo...

深度测评:Vue、React 一键部署的神器 PinMe

不知道大家有没有这种崩溃瞬间:领导突然要看项目Demo,客户临时要体验新功能,自己写的小案例想发朋友圈;找运维?排期?还要走工单;自己买服务器?域名、SSL、Nginx、防火墙;本地起服务?断电、关...

超简单!一键启动多容器,解锁 Docker Compose 极速编排秘籍

想要用最简单的方式在本地复刻一套完整的微服务环境?只需一个docker-compose.yml文件,你就能一键拉起N个容器,自动组网、挂载存储、环境隔离,全程无痛!下面这份终极指南,教你如何用...

日志文件转运工具Filebeat笔记_日志转发工具

一、概述与简介Filebeat是一个日志文件转运工具,在服务器上以轻量级代理的形式安装客户端后,Filebeat会监控日志目录或者指定的日志文件,追踪读取这些文件(追踪文件的变化,不停的读),并将来自...

K8s 日志高效查看神器,提升运维效率10倍!

通常情况下,在部署了K8S服务之后,为了更好地监控服务的运行情况,都会接入对应的日志系统来进行检测和分析,比如常见的Filebeat+ElasticSearch+Kibana这一套组合...

如何给网站添加 https_如何给网站添加证书

一、简介相信大家都知道https是更加安全的,特别是一些网站,有https的网站更能够让用户信任访问接下来以我的个人网站五岁小孩为例子,带大家一起从0到1配置网站https本次配置的...

10个Linux文件内容查看命令的实用示例

Linux文件内容查看命令30个实用示例详细介绍了10个Linux文件内容查看命令的30个实用示例,涵盖了从基本文本查看、分页浏览到二进制文件分析的各个方面。掌握这些命令帮助您:高效查看各种文本文件内...

第13章 工程化实践_第13章 工程化实践课

13.1ESLint+Prettier代码规范统一代码风格配置//.eslintrc.jsmodule.exports={root:true,env:{node...

龙建股份:工程项目中标_龙建股份有限公司招聘网

404NotFoundnginx/1.6.1【公告简述】2016年9月8日公告,公司于2016年9月6日收到苏丹共和国(简称“北苏丹”)喀土穆州基础设施与运输部公路、桥梁和排水公司出具的中标通知书...

福田汽车:获得政府补助_福田 补贴

404NotFoundnginx/1.6.1【公告简述】2016年9月1日公告,自2016年8月17日至今,公司共收到产业发展补助、支持资金等与收益相关的政府补助4笔,共计5429.08万元(不含...

取消回复欢迎 发表评论: