Py学习  »  Python

我要偷偷的学Python,然后惊呆所有人(第二天)

看,未来 • 3 年前 • 412 次点击  

在这里插入图片描述

标题无意冒犯,就是觉得这个广告挺好玩的
上面这张思维导图喜欢就拿走,反正我也学不了这么多

前言

前期回顾: 我要偷偷学Python,然后惊呆所有人(第一天)
上面这篇里面写了python的一些知识基础,从数据类型到四则运算,再到分支、循环。

那么今天,我们就看一下比较抽象的函数和类,如果对基础还不是很熟练的话可以再扎实一下基础,毕竟万丈高楼平地起嘛,基础不老实是很危险的。

本系列文默认各位有一定的C或C++基础,因为我是学了点C++的皮毛之后入手的Python,这里也要感谢齐锋学长送来的支持。
本系列文默认各位会百度,会用在线编译器,因为我是突击学Python的,之前的编译环境都删了,但是吧,我发现在线编译是真的爽,浪费那时间去搭那环境干啥,学好了Python,会差那点请人搭环境的钱吗?

我要的不多,点个关注就好啦
然后呢,本系列的目录嘛,说实话我个人比较倾向于那两本 Primer Plus,所以就跟着它们的目录结构吧。

本系列也会着重培养各位的自主动手能力,毕竟我不可能把所有知识点都给你讲到,所以自己解决需求的能力就尤为重要,所以我在文中埋得坑请不要把它们看成坑,那是我留给你们的锻炼机会,请各显神通,自行解决。
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

好,接下来切入正题。


编程学习的瓶颈

先来聊点轻松的嘛,一上来就讲那些佶屈聱牙的多没意思啊。

不论大家是有基础,还是没基础;是学过编程,还是学过数学;多多少少都会遇上硬茬。比方说我,在学习编程的路上遇到的第一个问题就是函数传参,哇靠,当时,我意气风发,毕竟咱是C++考了九十分的人,要横着走。但是到企业里面培训的第一天,老师给我们看了(讲解)一段代码的时候,整个人就给我整懵逼了,是一个结构体作数据类型的参数,是一堆这样的参数放在同一个函数里面。。。

然后在另一个地方,准确的说是另一个文件里面,调用这个函数,当时我听得一愣一愣的,连录屏都忘了录,等到我自己实操的时候。。。
传什么?传到哪里???晕死。。。

好啊,扯远了,大家可以在评论区打出自己遇到的瓶颈,说不定你的苦思冥想,其他人早已有了解决方案。

一山放过一山拦啊,能看懂代码只是基础的第一步,你还要自己写。自己写的时候就容易遇上各种各样的问题了,第二道坎,就是debug。

说多了都是泪,后面都会教大家这些技能,这篇我们先来看一下函数和类,后面再讲分文件项目、Debug、基本的项目设计与架构等东西,喜欢的话可以跟进。


函数其实没那么可怕

初始函数

函数是吗?学过中学数学的都知道函数吧。
此函数,非彼函数。

函数是组织好的,可重复使用的,用来实现单一,或相关联功能的代码段
函数能提高应用的模块性,和代码的重复利用率。你已经知道Python提供了许多内建函数,比如print()。但你也可以自己创建函数,这被叫做用户自定义函数。

定义一个函数

一图胜千言:
在这里插入图片描述

示例:

def math(x):
    y = 3*x + 5
    return y
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

这个函数用于实现:y = 3x+5 的求值,这里的x就是参数,别急,这里的规矩很多,听我慢慢讲。

首先各位有没有编译器,碧如pycharm之类的,没有也没关系,在线编译器还是很多的,碧如“编程中国”,选择Python编程。
把上面这一段先拿去编译一下,运行一下,不会运行的朋友可以百度一下。

运行之后你会发现根本没什么东西嘛,这不是骗人嘛,对,这不是骗人,咱又没调用,自然没东西。

函数规则

函数代码块以 def 关键词开头,后接函数标识符名称和圆括号(),括号后面要紧跟冒号,不然会报错。def就相当于告诉编译器:我这里是一个函数,你注意一下哈

任何传入参数必须放在圆括号中间,关于这个参数的规矩嘛:
1、在调用函数时,对函数进行参数传递必须与函数声明时的参数列表对应。
2、函数声明时可以声明默认参数,在函数调用时如果没有对默认参数进行传值,这默认参数使用预设值,默认参数要放在参数列表最右侧
3、函数外传参的参数数据类型须一一对应(有些可以强转,碧如floatint4、参数类型多种多样,并不局限于常见的intfloatstr等参数类型,也可以传类对象等

函数内容以冒号起始,并且缩进。

return [表达式] 结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回 None。

对于函数的调用,直接输入函数名,并传入参数(这里不考虑跨文件)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

具体的,多看。

示例2:

# 定义函数
def printme( str ):
   "打印任何传入的字符串"
   print(str)
   return
 
# 调用函数
printme("我要调用用户自定义函数!")
printme("再次调用同一函数")
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

示例3:

def menu(appetizer, course):
    print('一份开胃菜:' + appetizer)
    print('一份主食:' + course)
menu('话梅花生','牛肉拉面')
def list(list1,list2):
    print('fast food:'+list1)
    print('slow food:'+list2)
list('宫保鸡丁','水煮鱼')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

结果:

一份开胃菜:话梅花生
一份主食:牛肉拉面
fast food:宫保鸡丁
slow food:水煮鱼
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

示例4:

默认参数法:

def menu(appetizer, course, dessert = '绿豆沙'):
    print('一份开胃菜:' + appetizer)
    print('一份主食:' + course)
    print('一份甜品:' + dessert)


menu('话梅花生','牛肉拉面')
menu('话梅花生','牛肉拉面','银耳羹')
#银耳羹对应参数dessert
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

结果:

一份开胃菜:话梅花生
一份主食:牛肉拉面
一份甜品:绿豆沙
一份开胃菜:话梅花生
一份主食:牛肉拉面
一份甜品:银耳羹
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

示例5:

不定长参数

它的格式比较特殊,是一个星号*加上参数名,它的返回值也比较特殊,我们来看看下面的例子。

def menu(*barbeque):
    return barbeque

order = menu('烤鸡翅','烤茄子','烤玉米')
#括号里的这几个值都会传递给参数barbeque

print(order)
print(type(order))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

结果:
你会发现函数返回的是这样的结果:(‘烤鸡翅’, ‘烤茄子’, ‘烤玉米’),我们用type()函数可以知道这种数据类型叫作元组(tuple)

和列表一样,元组是可迭代对象,这意味着我们可以用for循环来遍历它,这时候的代码就可以写成:

def menu(*barbeque):
    for i in barbeque:
        print('一份烤串:' + i)

menu('烤香肠', '烤肉丸')        
menu('烤鸡翅', '烤茄子', '烤玉米')
# 不定长参数可以接收任意数量的值
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
一份烤串:烤香肠
一份烤串:烤肉丸
一份烤串:烤鸡翅
一份烤串:烤茄子
一份烤串:烤玉米
  • 1
  • 2
  • 3
  • 4
  • 5
  • 1
  • 2
  • 3
  • 4
  • 5

全局变量和局部变量

定义在函数内部的变量拥有一个局部作用域,定义在函数外的拥有全局作用域。

局部变量只能在其被声明的函数内部访问,而全局变量可以在整个程序范围内访问。调用函数时,所有在函数内声明的变量名称都将被加入到作用域中。

total = 0 # 这是一个全局变量
# 可写函数说明
def sum( arg1, arg2 ):
   #返回2个参数的和."
   total = arg1 + arg2 # total在这里是局部变量.
   print("函数内是局部变量 : ", total)
   return total
 
#调用sum函数
sum( 10, 20 )
print("函数外是全局变量 : ", total)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11

输出结果:

函数内是局部变量 :  30
函数外是全局变量 :  0
  • 1
  • 2
  • 1
  • 2

我再想想还差些啥哈。

哦,多函数嵌套。
就像俄罗斯套娃一样,一个函数中还能有另一个函数。

其实这个很好理解,想想print,它就是个函数,前面不就经常把print放在别的函数里面使用了嘛。


函数小项目

写一个小型计算器,支持四则运算,不带括号,带括号的太难了吧。

在这里插入图片描述


物以 “类” 聚

什么是类?什么是对象?
现在的高级编程语言吧,它都有一个门槛,就是你得是面向对象编程的,而面向对象编程,你要有类的支持。
那么什么是面向对象编程呢?就是描述一类事务的特征与功能,就比方说人类,那么对象就是人,人类这个类当中就要实现人的特征和功能。
特征:

没什么毛
两个肩膀扛一个脑袋
等等
  • 1
  • 2
  • 3
  • 1
  • 2
  • 3

技能:

直立行走
使用火
能写字
等等
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

是吧,将这些特征和技能集合在一起中,就是人类。

再讲两个概念,对象和实例:
对象是什么呢,就是你要构造的这个类,是以什么为模型构造的,拿上面那个人类的例子来说,可以理解为女娲捏人时的模子,女娲在面对‘人’这个对象捏土。
实例是什么呢?就是通过这个类构造出来的,具有类的一切特征和功能的玩意儿,可以理解为女娲捏出来的一个个实实在在的人。

类的创建

在这里插入图片描述

看图说话,一图胜千言。

类的实例化

在这里插入图片描述

类的调用

在这里插入图片描述

来,整理一下一条龙服务:
创建一个人类,他有两条腿,他能跑能跳,怎么写?这么写:

class People:
	leg = 2
	def run(self):
		print('他是一个人,他能跑')
	def jump(self):
		print('He is a man,he can jump')

lihua = People()
lihua.run()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

好,这里面还有点没讲清楚的,碧如说那个‘self’,到底是干嘛的。

  1. self,顾名思义嘛。好,我们直接看怎么用。
class People:
	leg = 2
	def run(self):
		print('他是一个人,他有%d条腿,所以他能跑',self.leg)
	def jump(self):
		print('He is a man,he can jump because of his %d legs',legs)

lihua = People()
lihua.run()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

如果要在类的外部调用类属性,我们得先创建一个实例,再用实例名.属性的格式调用,

那么如果想在类的内部调用类属性,而实例又还没创建之前,我们就需要有个变量先代替实例接收数据,这个变量就是参数self。

self的作用相当于先给实例占了个位置,等到实例创建好就“功成身退,退位让贤”。

同理,如果想在类的方法内部调用其他方法时,我们也需要用到self来代表实例。

  1. 初始化方法
    在C++中,有类的初始化,那Python的类里面肯定也是会有的啊。那我们来看一下栗子:

定义初始化方法的格式是def init (self),是由init加左右两边的【双】下划线组成( initialize “初始化”的缩写)。
初始化方法的作用在于:当每个实例对象创建时,该方法内的代码无须调用就会自动运行。

class


    
 People:
	def __init__(self):
		print('恭喜你,你造了个人')
lihua1 = People()
  • 1
  • 2
  • 3
  • 4
  • 1
  • 2
  • 3
  • 4

这是一种,再来一种

class People:
	def __init__(self,num):
		self.num = num
	def born()
		print('恭喜你,你获得了'+self.num+'个好朋友')
lihua2 = People()
lihua2.born()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

分水岭,难度再拔高

类的继承

什么是继承,在C++里面继承还是很好玩的,就像你的父亲是一个类,你继承了你父亲的一些特征与技能,也可以有自己的技能,这就是继承。

在这里插入图片描述

然后我们来实现一下上面所说的:

class Father:
	skin = 'yellow'
	def clever():
		print('他是个聪明人')

class Son(Father):
	def strugle():
		print('他很努力')

lihua = Son()
lihua.clever()
print(lihua.skin)
lihua.strucle()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

类的多继承

一个类,可以同时继承多个类,语法为class A(B,C,D):

这里各位可以自己实现一下一个人,继承了自己父母亲双方的优点,比如说父亲聪明,母亲好看,他又聪明又好看,还上进。

小tip:就近原则:越靠近子类(即越靠左)的父类,越亲近,越优先考虑。子类调用属性和方法时,会先在靠左的父类里找,找不到才往右找。

在这里插入图片描述

多学一点:
在这里插入图片描述


父类函数重写

重写代码,是在子类中,对父类代码的修改。

简单的举个栗子,其实这个还是很重要的一点:

class Father:
	skin = 'yellow'
	def clever():
		print('他的智商100')

class Son(Father):
	def clever():
		print('他的智商110')
	def strugle():
		print(


    
'他很努力')
lihua = Son()
lihua.clever()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

实战小项目

这里,我们来实现一个家族传承的小故事,来巩固一下我们今天学习的东西:

他本家境优渥,他的太爷爷白手做纱布生意白手起家,到了他爷爷这一代,生意进一步扩大,新增了药店生意、钱庄生意,到了他父亲这一代,倭寇入侵,时局动荡,百姓流离,于是他的父亲毅然决定开棚赈粥,开铺放药,就这么坚持了几年之后,终于散尽家财,但是他们无怨无悔。国破山河在?

到了他这一代,响应国家中华民族伟大复兴的口号,他苦练技术,期待着有一天能重整家族的辉煌···

哎,后续各位自己编,我们来实现四个类:他太爷爷,他爷爷,他爸,他。把这一条故事线串一串。

加油!!

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

持续更新中,喜欢的可以跟进哦

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/74353
 
412 次点击