现如今,大数据的发展越来越好,也越来越多的企业中大数据分析已经朝着更好的方向发展。也正是因为这个原因,数据分析行业的人才需求也变得火爆起来,尤其是数据分析、数据挖掘、数据科学家等高端人才,越来越稀缺。
当然,对于数据分析这个工作,的确是需要学会一些编程语言的,比如MATLAB,Python,Java等语言。但是对于初学者来说,Python是一个不错的语言,Python语言简单易懂还具有强大的编程能力,同时对于大数据分析有很明显的帮助。
0基础无障碍学习Python系列专题(一)
今天的主要关键内容是我们Python中最基础的两个部分,变量名命名规则和字符串方法。在处理数据的过程中,我们需要创建一些变量名进行赋值,那变量名命名时有什么规则呢?
变量名命名规则变量名由数字、字母、下划线组成。但不能以数字开头
命名时应当避开关键字。
#查看python关键字
import keyword
kw = keyword.kwlist
print(kw)
#运行结果
['False', 'None', 'True', 'and', 'as', 'assert', 'async', 'await', 'break', 'class', 'continue', 'def', 'del', 'elif', 'else', 'except', 'finally', 'for', 'from', 'global', 'if', 'import', 'in', 'is', 'lambda', 'nonlocal', 'not', 'or', 'pass', 'raise', 'return', 'try', 'while', 'with', 'yield']
在Python中方法相当于函数功能,Python为我们提供了许多方法便于我们处理数据,接下来我们接触几个简单的字符串方法。体验一下他们神奇。
字符串方法center 通过在两边添加填充字符(默认为空格)让字符串居中
b = "我想居中"
print(b.center(80))
print(b.center(80,"-")) 我想居中
--------------------------------------我想居中--------------------------------------find 在字符串中查找子串。如果找到,就返回子串的第一个字符的索引,否则返回-1
index 在字符串中查找子串。如果找到,就返回子串的第一个字符的索引,否则引发ValueErorr异常
h = 'my name is Lexi'
print(h.find('m'))
print(h.index('n'))
#两个函数都可限制搜索范围
print(h.find('n',0,2)) #同时制定起点和终点
print(h.index('n',2)) #只制定了起点join 用于合并序列的元素
#合并一个字符串列表
sep = ["1","3","4","5"]
seq = '+'
seq.join(sep)
#用 join 地址拼接场景
dirs = '','usr','bin','env'
print('C:'+'\\'.join(dirs))lower 返回字符串的小写版本
'Hello World'.lower()
'classical my girl'.title() #首词大写
#在string模块中有个capwords可以实现首词大写
import string
string.capwords("that's your book")replace 将指定的子串都替换为另一个字符串,并返回替换后结果
'this is your book'.replace('is','eez')split 返回一个列表,按照分割符进行划分
'1+2+3+4+5'.split('+')strip 删除指定字符
rstrip 从右边删除指定字符
lstrip 从左边删除指定字符
#去除输入的空格
k = input("请输入一个数字")
print(k.strip())
#去除指定的字符(只能去除开头或者结尾的字符,中间的还是会被保留)
clear = '###$%%^^%$#^!#!$!'
print(clear.strip("#"))
0基础无障碍学习Python系列专题(二)
主要关键内容列表新建索引
切片
序列的加法和乘法
成员资格
列表方法元组
字典字典常用方法
写在前面Python内置了多种序列,列表和元组是其中最常用的两种;
列表和元组的主要区别在于,列表可以修改,而元组不可以;
常规操作包括索引、切片、插入、删减等。
列表新建新建一个列表;
列表由中括号为容器,每个元素之间用逗号间隔。
#新建一个列表:
alist = [1,"nihao","hello","你好"]
print(alist)
索引列表中所有元素都有编号—从0开始递增;
列表中第一个元素编号为0,最后一个元素编号为-1。
alist = [1,"nihao","hello","你好"]
alist[0] #取出alist中的第一个元素1
alist[-1] #取出alist中的最后一个元素"你好"
alist[2] #取出alist中的第三个元素"hello"
切片用索引我们可以访问单个元素,而切片可以让我们访问多个元素
使用两个索引值,并用冒号分隔
blist = [1,2,3,4,5,6,7,8,9,10] #新建一个列表blist
blist[0:3] #取出blist中前3个元素[1,2,3]
blist[7:10] #取出blist中后3个元素[8,9,10]
#添加步长参数
blist[0:4:2] #按步长为2,取出blist中前4个元素.[1,3]
#小应用:提取域名
wangzhi = input("请输入网址") #输入http://www.xiaokeai.com
yuming = wangzhi[11:-4] #截取域名
print(yuming) #返回 xiaokeai
序列的加法和乘法
[1,3,4]+[4,6,7] #运行结果为[1, 3, 4, 4, 6, 7]
[1,3,4]*4 #运行结果为[1, 3, 4, 1, 3, 4, 1, 3, 4, 1, 3, 4]
成员资格用in判断元素是否在列表中,存在返回True,不存在返回False
#判断输入的内容是否存在
users = ["王二麻子","李大嘴","赵四","大墩子"] #简历列表users
user_name = input("请输入你的名字:") #输入
user_name in users
列表方法append 将一个对象附加到列表结尾
insert 将一个对象插入到列表中的指定位置
extend 将多个值添加进列表末尾
lst = [3,7,32,8,13,34] #创建新列表lst
lst.append(3) #添加新元素3
print(lst) #打印结果[3, 7, 32, 8, 13, 34, 3]
tst = [3,7,32,8,13,34] #创建新列表tst
tst.insert(3,"hello") #插入新元素,使得新元素的索引为3
print(tst) #打印结果[3, 7, 32, 'hello', 8, 13, 34]
ist = [3,7,32,8,13,34] #创建新列表ist
a = [1,3,4] #创建新列表a
ist.extend(a)
print(ist) #打印结果[3, 7, 32, 8, 13, 34, 1, 3, 4]
#extend添加与加法(ist+a)的主要区别是,extend改变了ist的内容,而加法没有改变istcopy 复制列表
count 计算出指定的元素在列表中出现了多少次
index 查找指定值第一次出现的索引
a = [1,2,3] #创建新列表a
b = a.copy() #将a复制给b
print(b) #输出结果[1,2,3]
b[1] = 4 #改变b中的元素
print(a,b) #a不会被改变,输出[1, 2, 3] [1, 4, 3]
k = ["two","to","san","two",["two","two"]] #新建列表k
k.count("two") #统计k中"two"的个数,返回结果2
k.index("to") #返回to第一次出现的索引值,结果为1pop 从列表中删除末尾元素,并返回这一元素
remove 用于删除第一个为指定值的元素
clear 清空列表内容
del 删除列表中元素(del语句不属于方法)
x = [1,2,3] #创建新列表x
x.pop() #删除了最后一个元素,并返回3
print(x) #输出结果[1,2]
y = [4,65,86,4,56,5] #创建新列表y
y.remove(4) #删除列表中第一个4
print(y) #输出结果[65, 86, 4, 56, 5]
j = [5,432,5425.6,51] #创建新列表j
j.clear() #清除列表
print(j) #打印结果[]
l = ["to","be","am","is","are"] #创建新列表l
del l[2] #删除l中索引为2的元素
print(l) #输出结果['to', 'be', 'is', 'are']sort 对列表进行排序,默认为从小到大排序,或者按字母顺序排序。调整参数可以调整排序方式。
h = [32,54,6,8,2,543,6576,243]
h.sort()
print(h) #输出结果[2, 6, 8, 32, 54, 243, 543, 6576],按数字大小
h.sort(reverse=True)
h.reverse()
print(h) #调整sort中reverse参数或者直接使用reverse方法可以倒序排序,输出结果为[6576, 543, 243, 54, 32, 8, 6, 2]
y = ["p","y","t","h","o","n"]
y.sort()
print(y) #输出结果['h', 'n', 'o', 'p', 't', 'y'],按字母先后顺序
name = ["dhjak ","jkl","dsafd","dasjkdal"]
name.sort(key=len) #调整sort的key参数,可以实现按文本长度排序
print(name) #输出结果['jkl', 'dsafd', 'dhjak ', 'dasjkdal']
元组以小括号形式体现的数据集,不同元素之间用逗号隔开;
元组许多功能与列表相似,唯一区别是不能进行修改元素。语法也很简答,在这就不一一赘述。
字典字典由“{}”、“键”以及“值”组合而成,键和值之间用“:”相连。每个键值对之间由“,”相隔;
字典是一种无序的映射的集合。包含若干个键值对;
其中字典中的键通常采用字符串,但也可以用数字、元组等类型;字典值则可以是任意类型。
思考:有了列表和元组两个容器,我们为什么还需要用字典呢?
接下来给大家举一个例子,用该例子说明我们字典的优势。
#开学了,现在我们这有一份学员名单,以及每个学员的性别,如下:
name = ["zhao","qian","sun","li","zhou","wu","zheng","wang"]
gender = ["F","M","F","F","M","F","M","M"]
#现在我们想知道同学"sun"的性别,于是我们写了以下代码:
print(gender[name.index("sun")])
#上面这行代码当然是可以为我们反馈正确结果的,但是这个代码写起来非常麻烦。如果我们建立了字典,将会大大简化我们的代码。步骤如下:
xueyuan = {"zhao":'F',"qian":'M',"sun":'F',"li":'F',"zhou":'M',"wu":'F',"zheng":'M',"wang":'M'}
print(xueyuan["sun"])
从刚才这个小例子,我们看到了字典的优势,也知道了如何建立字典容器。接下来我们来看字典的基本操作:len(dict)返回dict字典中包含的项(键值对)个数;
dict[a]返回与键a相关联的值;
dict[b] = value 讲b值关联到key2;
del dict[c] 删除c的项;
e in d 检查字典d是否包含键为e的项;
dict1 = {"name":"zhang","age":10} #创建字典
print(len(dict1)) #用函数len()求出字典dict1的键值对个数,返回2
print(dict1["name"]) #通过"[键]"可以查出该键所对应的的值,返回"zhang"
dict1["age"]=12 #更改age所对应的值
print(dict1) #返回结果{'name': 'zhang', 'age': 12}
del dict1["age"] #删除"name"项
print(dict1) #返回结果{'name': 'zhang'}
"name" in dict1 #检查字典dict1中是否包含"name"项,返回True
字典的常用方法pop() 从字典中删除,并返回映射值
popitem() 从字典中删除并返回键值对元组
clear() 删除字典内的全部对象
d1 = {"a":1,"b":2,"c":3} #创建字典d1
d1.pop("a") #删除键为a的键值对,并且返回值1
print(d1) #返回{'b': 2, 'c': 3}
d1.popitem() #随机的删除d1中某一对键值对,并返回键值对元组。因为字典是无序的,不能确定他每次删除的是哪一项键值对。如果本身字典为空,在执行该语句会报错。
d1.clear() #清除字典内全部对象
print(d1) #返回{}copy() 复制字典对象
x = {"name":"张三","age":"9"} #创建一个字典
y = x #直接复制时,x和y引用同一个字典
print(x,y) #返回{'name': '张三', 'age': '9'} {'name': '张三', 'age': '9'}
y["name"]="李四" #将y中键"name"的值改为"李四"
print(x) #x也跟随改变,{'name': '李四', 'age': '9'}
#可以用方法copy()解决这个问题
y = x.copy() #y引用复制字典
y["name"] = "王五" #讲y中键"name"的值改为"王五"
print(y,x) #x也跟随改变,{'name': '王五', 'age': '9'} {'name': '李四', 'age': '9'}get(key[,default]) 返回key键映射的值。如果key不存在,返回空值。可以用default参数指定不存在的键的返回值。如下例
x = {"name":"张三","age":"9"} #创建一个字典
x.get("name") #返回键"name"对应值"'张三'
x.get("gender") #没有"gender"键,所以返回空
x.get("gender","none") #设定default参数,当没有"gender"键,返回"none"setdefault(key[,default]) 用该方法返回映射值或者添加键值对。
upgrade() 为字典添加键值对,若字典已存在同名的键,则映射值被覆盖。
x = {"name":"张三","age":"9"} #创建一个字典
x.setdefault("name") #返回键"name"对应值"'张三'
x.setdefault("gender") #添加新键值对
print(x) #返回{'name': '张三', 'age': '9', 'gender': None},默认给None值
x.setdefault('phone','123') #添加新键值对
print(x) #返回{'name': '张三', 'age': '9', 'gender': None, 'phone': '123'}items() 返回键值对视图
keys() 返回字典中所有键的视图
values() 返回字典中所有值的视图
y = {'name': '张三', 'age': '9', 'gender': None, 'phone': '123'} #创建一个字典
x.items() #返回键值对视图 dict_items([('name', '张三'), ('age', '9'), ('gender', None), ('phone', '123')])
x.keys() #返回所有键的视图 dict_keys(['name', 'age', 'gender', 'phone'])
x.values() #返回所有值的视图 dict_keys(['name', 'age', 'gender', 'phone'])
0基础无障碍学习Python系列专题(三)
主要关键内容:函数编写与传参方式函数是组织好的,可重复使用的的代码段;
函数能提高应用的模块性,和代码的重复利用率。
定义函数与调用函数以 def 关键词开头,后接函数名,函数名后接 ();
()之间可以用于定义参数;
函数内容以冒号起始,并且转行缩进;
return代表着函数结束,选择性地返回一个值给调用函数。
#定义函数基本格式如下:
def 函数名(参数表):
函数语句
return 返回值
#参数和返回值都不是必须有的,例如:
def hello(): #定义函数
print("hello world")
hello() #调用函数,返回hello world
#而下面这个例子是为函数定义了两个参数,并用return语句返回值。
def add(a,b): #定义函数
return(a+b)
add(1,3) #调用函数,返回4
函数参数(重点)定义函数时,参数表中的参数称为形式参数,简称形参;
调用函数时,参数表中的参数称为实际参数,简称实参。
参数具有多态性传入不同类型变量,得到不同结果。
def duo(a,b): #定义函数
return(a+b)
duo(1,4) #调用传入两个int值,返回结果5
duo("oh"," my god") #调用并传入两个字符串,返回结果'oh my god'
duo((3,4),("g","h")) #调用并传入两个元组,执行元组合并,返回(3, 4, 'g', 'h')
duo([7,4],[6,7,8,9]) #调用并传入两个列表,执行列表合并,返回[7, 4, 6, 7, 8, 9]
参数赋值传递函数调用时按参数的先后顺序,将实参传递给形参;
可以以形参赋值的方式,指定将实参传递给形参。
def fu(a,b):
return(a+b) #定义函数
fu("ab","cd") #返回"abcd",按对应位置将实参传递给了形参;
fu(b="cd",a="ab") #依然返回"abcd",通过形参赋值传参。
可变参数(小心使用)当实参是可变对象时,如列表、字典。如在函数中修改形参,因为共享引用。通过实参也获得修改后的对象;
详见以下例子。
def kebian1(k): #定义函数
k[1] = "hello"
x = [9,10]
kebian1(x) #调用函数,传递列表对象的引用
print(x) #返回[9, 'hello'],变量原本的引用被修改
#嗯哼~那么问题来了!!我们应该如何规避这个问题?(看下行的时候请先思考)
#------------------------------------------------------------------
#我们规避的思路就是,复制一份,将克隆的传入形参。原本变量不受影响,如下例:
k = [1,2]
kebian1(k[:]) #调用函数,传递拷贝下来的变量
print(k) #返回[1, 2],变量没被改变
#还可以在函数内对列表进行拷贝,如下例:
def kebian2(k): #定义函数
k = q[:] #拷贝
k[1] = 'hello'
q = [3,4]
kebian2(q) #调用函数,传递列表对象的引用
print(q) #返回[3, 4],变量没被改变
参数默认值在定义函数的时候,我们可以给参数设置一个默认值。这样我们在调用函数未提供实参时,函数将按照默认参数执行;
带默认值的参数,应当放在参数表的末尾;
为避免出错,默认参数必须指向一个不可变参数。
def info(name = "",degree = "未填写"): #定义函数,并将参数degree赋予一个默认值“未填写”
print(name,degree)
info("熊猫酱") #当只输入一个实参时,会返回熊猫酱 未填写
info("熊猫酱","博士") #当输入两个实参时,会返回熊猫酱 博士
传递任意个参数定义函数是,若参数名前带有"*"号,则表示可接受任意个数的参数,并保存在一个元组中;
传参时,"*"号后面的参数必须以关键字传参。
def add(a,*b,c): #定义函数
s = a+c
for i in b: #为了保证语法不出错,当函数带有"*"号的参数时,需要用for循环来循环元组内内容
s += i
return s
add(1,2,4,c=9) #返回结果16,注意*b,后面的参数,传参是必须带上关键字。
0基础无障碍学习Python系列专题(四)
主讲关键内容:Python的面向对象
Python的类在这门语言中,类使用 class 语句来定义。在类中包含了一系列语句,比如赋值语句,def 定义函数等。从面向对象的角度看,类封装了对象的行为和数据。在Python的类中变量就是对象的数据,函数就是对象的行为,函数也成为方法。
Python中的对象在Python的对象模型中,有两种对象:类对象和实例对象。类对象是用 class 语句创建的,而实例对象是在调用类的时候创建的。所以类对象只有一个,而实例对象可以有多个。
类对象执行 class 语句创建一个类对象和一个变量;
类中的赋值语句创建的变量是类的数据属性,在类中的顶层赋值语句创建的变量才属于类属性;
类中定义的 def 语句的函数是类的方法属性;
类的数据和方法和所有实例对象共享。
实例对象实例对象通过调用类对象来创建;
每个实例对象继承类对象的属性,并获得自己的命名空间;
实例对象可以拥有“私有”属性。类的方法函数的第一个参数默认为 self,表示引用方法的对象实例。在方法中地域 self 的属性赋值才会创建术语实例对象的属性
[^]: 摘自《python3基础教程》侵删 。这个是本文作者看了诸多教材后,从中对比出最简单理解的一版。肯定还是很枯燥,但如果是零基础的读者还是要硬着头皮看完再看后面的内容。
定义类
基本格式如下代码:
class Student: #创建了一个名为Student的类,我们约定类的首字母大写。
data = 200 #在此,我们定义了类的属性.
def set_name(self,name): #用def语句定义了类的方法
self.name = name
def show_name(self):
return self.name
print("类Student创建完成")
调用类
type(Student) #首先我们检查一下我们类的类型,返回type
Student.data #调用了类的属性,返回200
Student.set_name() #试图调用类的方法,会直接报错。类的方法并不能直接调用,只能通过实例对象调用。
#正确调用类方法的姿势如下:
banji1 = Student() #创建一个实例对象banji1
banji1.set_name("amy") #传入参数
banji1.show_name() #调用方法,显示实例对象属性值,返回'amy'
banji2 = Student() #创建另一个实例对象banji2
banji2.set_name('tom') #传入参数
banji2.show_name() #调用方法,显示实例对象属性值,返回'tom'。从这可看出,实例对象属性之间没有什么关系。
banji1.data,banji2.data #返回(200, 200),访问了共享属性
对象的属性
在Python中,实例对象继承了类对象的所有属性和方法,可以用dir()函数查看
dir(Student)
dir(banji1)
#这个代码返回信息太长,可以自行运行查看一下。以双下划綫开头结尾的变量名术语内置属性,最后我们可以看到来自Student类对象的data、set_name、show_name三个属性。
共享属性
类对象的数据属性是全局的,改变类对象的属性,实例对象引用时也会被改变。实例对象的数据属性更改不影响其他实例对象或者类对象。
banji3 = Student() #创建Student的实例对象,并用banji3引用该对象
banji4 = Student() #创建Student的实例对象,并用banji4引用该对象
print(Student.data,banji3.data,banji4.data) #返回200 200 200
Student.data = 100 #改变全局变量属性
print(Student.data,banji3.data,banji4.data) #返回100 100 100,实例对象属性跟随改变
banji3.data = 400 #更改实例变量的data属性赋值
print(Student.data,banji3.data,banji4.data) #返回100 400 100,实例对象属性改变,不影响他人
实例对象可以拥有私有属性
“私有”强调属性只属于当前实例对象,对其他实例对象是不可见的。
banji5 = Student() #创建Student的实例对象,并用banji5引用该对象
# banji5.set_name() #试图访问实例对象的属性,结果报错显示并不存在
banji5.set_name("john") #调用类的对象方法为属性赋值
banji5.show_name() #返回"john"
类的私有属性
如果想要类的方法或者属性成为私有的,不能通过实例对象引用,只需要在期名称以两个下划线开头即可。如下例:
class Secret:
def __invisible(self):
print("you can't see")
def visible(self):
print("what you can not see is:")
self.__invisible()
#这样创建,我们就不能从外部访问__invisible,但是可以通过invisible访问
s = Secret()
# s.__invisible() #试图从外部访问,直接报错
s.visible() #访问成功,返回what you can not see is: you can't see
#其实,在类定义中,所有以两下划线开头的名称都被进行了转化,就是加了个下划线和类名
dir(Secret) #用dir查看,我们发现列表中有'_Secret__invisible',知道这个以后,我们可以从外部访问类的私有对象了
s._Secret__invisible() #成功返回you can't see。但这中操作并不正规
魔法函数init
又名构造函数,在调用类创建实例对象时自动被调用,不需要手动调用。
class Boy(object):
def __init__(self):
#方法,用来做变量初始化或赋值操作,在类实例化对象的时候,会被自动调用
self.name = "yyg"
self.height = "180"
self.weight = "170"
def info(self):
print("我叫{},身高{},体重{}".format(self.name,self.height,self.weight))
def show(self):
"""实例方法"""
print("你的嘤嘤怪以上线")
boyfriend = Boy()
# 只需要调用实例方法info(),即可获取数据
boyfriend.info() #返回我叫yyg,身高180,体重170
boyfriend.show() #返回你的嘤嘤怪以上线
0基础无障碍学习Python系列专题(五)
——那些被遗忘而好用的函数
主讲关键内容:
lambda函数
map()函数
递归函数
lambda 函数
最开始接触循环,我们就写了一个函数实现了1加到100。我们是这样写的:
my_sum = 0
for i in range(1,101):
my_sum += i
print(my_sum)
就像上面写的一样,代码非常简短明朗就能实现我们的需求。但是如果我们需求变成1加到1000或者50加到100等等我们就需要用到def函数。
def my_sum(x,y):
res = 0
for i in range(x,y):
res += i
return res
my_sum(50,101) #调用函数,返回3825
my_sum(1,1001) #调用函数,返回500500
lambda函数写起来非常简单,不需要命名函数,可以直接输出结果.经常与一些高级函数结合使用:lambda关键字后面跟参数,可以跟多个参数
参数后跟冒号,冒号后接的相当于return后面的内容
lambda定义的是单行函数,如果需要复杂函数,还是应该选择普通函数
lambda表达式中不能含有命令,而且仅限一条表达式
如果我们用lambda函数我们将两行搞定这件事情,如下:
from functools import reduce #python3.x以上需要导入reduce模块
reduce(lambda x,y:x+y,range(1,101))#正确返回结果5050
map()函数map()是 Python 内置的高阶函数
map函数一般第一个参数是一个函数,可以是内置函数,也可以是自定义函数;第二个参数一个可迭代对象
map将接收的函数,依次作用在可迭代对象的每一个元素中中并返回一个map对象,类似于这种格式
map对象可以转化成list,或者用遍历将他显示出来
list(map(lambda x:x*2,[1,2,3]))
#返回[2, 4, 6].此函数讲[1,2,3]中每个元素都按照lambda公式要求乘以2,并用list将他们转化成了列表格式
#利用map()函数与lambda结合,我们可以解决一个网红python题,找1000以内的水仙花数
#(“水仙花数”是一个三位数其各位数字的立方和等于该数本身)
for i in range(100,1000):
if sum(map(lambda x:int(x)**3,str(i)))==i:
print(i)
#这段简短代码可读性很高我就不一一细说了,你细品~
如果我们能结合自定义公式,那想找几位的水仙花数都非常easy啦,请看我的表演
def shuixianhua(n): #自定义函数shuixianhua
x = 10**(n-1)
y = 10**n
res = []
for i in range(x,y):
if sum(map(lambda z:int(z)**n,str(i))) == i:
res.append(i)
return res
shuixianhua(3) #返回[153, 370, 371, 407]
shuixianhua(4) #返回[1634, 8208, 9474]
递归函数递归函数指函数体体内调用函数本身;
使用递归函数,必须设定一个基线条件,就是满足这一条件时,直接返回一个值
以下是递归的经典案例:
1.阶乘问题:用我们之前所学的内容我们可以这样解决阶乘问题
#思路:先定义res变量为n,在让其一次乘以1到n-1每一个数字
def jiecheng(n):
res = n
for i in range(1,n):
res *= i
return res
jiecheng(3) #返回1*2*3的值,6如果用递归方法实现阶乘问题,我们首先要理清她的基线条件:
1的阶乘为1
大于1的数字n,其阶乘为n依次乘以1到n-1
def jc(n):
if n == 1: #如果是1,返回1
return 1
else:
return n * jc(n-1) #如果不是1,再次调用函数本身
jc(4) #返回1*2*3*4的值,24
2.幂问题
- 说到幂问题,要插播一个内置函数,pow(x,n),返回x的n次幂
- 然后再用普通姿势定义一个函数power,让他实现pow()的功能
#思路将n个x相乘
def power(x,n):
res = x
for i in range(1,n):
res *= x
return res
power(2,3)如果用递归方法实现幂问题,我们首先要理清她的基线条件:
1的0次方为1
def power(x,n):
if n == 0: #如果是0,返回1
return 1
else:
return x * power(x,n-1) #如果不是0,再次调用函数本身
power(2,3) #返回8
3.用递归函数解决一元二次函数求解问题
import math
def func(a,b,c):
delta = b**2-4*a*c
x = -b/(2*a)
if delta == 0:
print("只有一个根{}".format(x))
elif delta > 0:
x1 = x + math.sqrt(delta)/(2*a)
x2 = x - math.sqrt(delta)/(2*a)
print("有两个根,{},{}".format(x1,x2))
else:
print("无实根")
func(1,2,1)
0基础无障碍学习Python系列专题(六)
主讲关键内容:继承如果在子类中定义了__init__()方法,父类的__init__() 不会被自动调用,需要在子类中显示调用
子类中调用父类方法时,以父类类名为前缀,并以self做为第一个参数.区别于在类中调用普通函数是不需要带上self参数
Python总是首先在子类中查找对应方法,如果子类中没有找到,才会找到父类中逐个查找
#### 单继承当我们定义了一个类A,还需要建立一个B,但是A和B两者属性大致相同。那么可以利用继承的方法,让B继承A的属性,而不是重头开始写个B。
class University():
def __init__(self):
self.level = '双一流大学'
print("University:yes")
def getLevel(self):
print('University:self level is:',self.level)
class College(University):
pass
a = University() # 返回University:yes
a.getLevel() # 返回University:self level is: 双一流大学
b = College() # 返回University:yes
b.getLevel() # 返回University:self level is: 双一流大学
#在这个例子中,子类College默认没有__init__属性时,会直接继承父类University的__init__
#如果子类中有定义__init__,子类必须显示地在__init__()函数中再次调用父类的__init__()函数。
继承与抽象继承是基于抽象的过程
以下是大学里建立教职工与学员信息表的代码,如下:
class Teachers(): #建立教职工的类
def __init__(self,name,age,tea_id):
self.name = name
self.age = age
self.tea_id = tea_id
def say_hello(self):
print('My name is {},{} years old'.format(self.name,self.age))
print('I am a teacher,my id is {}'.format(self.tea_id))
class Students(): #建立学生的类
def __init__(self,name,age,stu_id):
self.name = name
self.age = age
self.stu_id = stu_id
def say_hello(self):
print('My name is {},{} years old'.format(self.name,self.age))
print('I am a student,my id is {}'.format(self.stu_id))Students和Teachers类都有共同的属性name和age,并且say_hello方式相同,可以对他们进行抽象,归类为People,建立派生类Sudents和Teachers。代码如下:
class People:
def __init__(self,name,age,id):
self.name = name
self.age = age
self.id = id
def say_hello(self):
print('My name is%s,%syears old'%(self.name,self.age))
print('My id is%s'%self.id)
class Students(People):
pass
class Teachers(People):
pass
p = Students('amy','18','o090909')
q = Teachers('john','22','i090979')
p.say_hello()
#返回结果如下:
# My name is amy,18 years old
# My id is o090909
q.say_hello()
#返回结果如下:
# My name is john,22 years old
# My id is i090979
覆盖现在需要解决的就是要区分出是老师还是学生
思路:
覆盖People中的say_hello方法
Students调用say_hello方法时多输出一句"I am a student",同理Teachers类多输出一句"i am a teacher"
调整后代码如下:
class People:
def __init__(self,name,age,id):
self.name = name
self.age = age
self.id = id
def say_hello(self):
print('My name is%s,%syears old'%(self.name,self.age))
print('My id is%s'%self.id)
class Students(People):
def say_hello(self):
People.say_hello(self) #调用父类方法
print('I am a student')
class Teachers(People):
def say_hello(self):
People.say_hello(self) #调用父类方法
print('I am a teacher')
p = Students('amy','18','o090909')
q = Teachers('john','22','i090979')
p.say_hello()
#返回结果如下:
# My name is amy,18 years old
# My id is o090909
# I am a student
q.say_hello()
#返回结果如下:
# My name is john,22 years old
# My id is i090979
# I am a teacher
多重继承子类可以继承多个父类
class Father1():
father1_data = 'this is father_1'
def father_1(self):
return 'this is father_1 def'
class Father2():
father2_data = 'this is father_2'
def father_2(self):
return 'this is father_2 def'
class Son(Father1,Father2):#子类Son同时继承Father1和Fahter2类
def son_def(self):
return 'this is son def'
s = Son()
print(s.father1_data) # 返回this is father_1
print(s.father2_data) # 返回this is father_2
s.father_1() # 返回'this is father_1 def'
s.father_2() # 返回'this is father_2 def'