一、函数
1. 定义:
def 函数名(参数1,参数2): ----(参数可有可无)
语句体
return 变量 ----(return可有可无)
2. 调用:
函数名
变量=函数名(参数1,参数2) ----(变量,参数可有可无)
① 调用 ②传参 ③ 接收返回值
3. 举例:
①第一种:无参无返回值
# 定义函数calc
def calc():
a = int(input('请输入第一个数:'))
b = int(input('请输入第二个数:'))
c = a + b
# print('结果为:',c)
print('结果为:%d'%c)
# 调用
calc()
运行结果为:
请输入第一个数:1
请输入第二个数:3
结果为:4
② 第二种:无参有返回值
def calc():
a = int(input('请输入第一个数:'))
b = int(input('请输入第二个数:'))
c = a + b
return c
# 调用
# print(calc())
result = calc()
print(result)
③ 第三种:有参有返回值
def calc(x,y):
c = x + y
return c
a = int(input('请输入第一个数:'))
b = int(input('请输入第二个数:'))
result = calc(a,b)
print(result)
4. 练习:设计一个计算器
① 输入两个数,自动实现加减乘除
x = int(input('请输入第一个数:'))
y = int(input('请输入第二个数:'))
def add():
z = x + y
return z
def sub():
z = x - y
return z
def mul():
z = x * y
return z
def div():
z = x / y
return z
print('两数相加为:',add())
print('两数相减为:',sub())
print('两数相乘为:',mul())
print('两数相除为:',div())
运行结果为:
请输入第一个数:6
请输入第二个数:2
两数相加为: 8
两数相减为: 4
两数相乘为: 12
两数相除为: 3.0
② 进阶:根据用户输入的计算符号计算结果
def calc():
x = int(input('请输入第一个数:'))
y = int(input('请输入第二个数:'))
z = input('请输入运算符号:+ - * /:')
if z == '+':
result = x + y
print('两数相加为:',result)
elif z == '-':
result = x - y
print('两数相减为:',result)
elif z == '*':
result = x * y
print('两数相乘为:',result)
elif z == '/':
try:
result = x / y
print('两数相除为:',result)
except ZeroDivisionError:
print('除数不能为0!')
else:
print('运算符号输入错误,请重新输入!')
calc()
5. 参数的几种类型:
① 位置参数:调用函数时根据函数定义的参数位置来传递参数
def person(name,sex):
sex_dict = {1:'先生',2:'女士'}
print('hello %s %s,welcome~'%(name,sex_dict.get(sex,'女士')))
person('baby',2)
运行结果为:
hello baby 女士,welcome~
注意:位置参数的两个参数的顺序必须一一对应,且少一个参数都不可以
② 默认参数:用于定义函数,为参数提供默认值,调用函数时可传可不传该默认参数的值
注意:定义默认参数时,必选参数在前、默认参数在后(包括函数定义和调用),否则python解释器会报错,且默认参数必须执行不变对象!
1)默认参数指向可变对象时:(保留了上次执行的结果)
def add_end(L = []):
L.append('end')
return L
print(add_end())
print(add_end())
运行结果:
['end']
['end', 'end']
2)默认参数指向不变对象时:
def add_end(L = None):
if L is None:
L = []
L.append('end')
return L
print(add_end())
print(add_end())
运行结果:
['end']
['end']
③ 可变参数:定义函数时,有时候我们不确定调用的时候会传递多少个参数(不传参也可以)。此时,可用位置参数,或者关键字参数,来进行参数传递
我们传进的所有参数都会被args变量收集,它会根据传进参数的位置合并为一个元组(tuple),args是元组类型,这就是位置传递
1)
def calc(*args):
print(*args) # *args打印出来是一个一个的整型的数
print(args,type(args)) # args默认保存为元组,打印出来是一个元组
for i in args:
print('传入的值分别为:',i)
# 可变参数传参形式1 - 常用(通过引用的方式必须带*)
m = [1,2,3]
calc(*m)
运行结果:
1 2 3
(1, 2, 3) <class 'tuple'>
传入的值分别为: 1
传入的值分别为: 2
传入的值分别为: 3
2)
def calc(*args):
print(*args) # *args打印出来是一个一个的整型的数
print(args,type(args)) # args默认保存为元组,打印出来是一个元组
for i in args:
print('传入的值分别为:',i)
n = (3,4,5)
calc(*n)
3)
def calc(*args):
print(*args) # *args打印出来是一个一个的整型的数
print(args,type(args)) # args默认保存为元组,打印出来是一个元组
for i in args:
print('传入的值分别为:',i)
# 可变参数传参形式2
calc(1,2,3)
④ 关键字参数:用于函数调用,通过“键-值”形式加以指定。可以让函数更加清晰、容易使用,同时也清除了参数的顺序需求。
有位置参数时,位置参数必须在关键字参数的前面,但关键字参数之间不存在先后顺序
kargs是一个字典(dict),收集所有关键字参数
def person(name,age,**kwargs):
print('name',name,'age',age,kwargs)
print(kwargs,type(kwargs))
person('xiaoming',21,sex = 'male',color = 'blue')
person('xiaoming',21) # 可变参数和关键字参数可以不传
person('xiaoming',21,sex = 1)
person('xiaoming',21,sex = 'male')
总结:
可变参数允许你传入0个或任意个参数,这些可变参数在函数调用时自动组装为一个tuple。
而关键字参数允许你传入0个或任意个含参数名的参数,这些关键字参数在函数内部自动组装为一个dict。
关键字参数有什么用?
它可以扩展函数的功能。比如,在person函数里,我们保证能接收到name和age这两个参数,但是,如果调用者愿意提供更多的参数,我们也能收到。试想你正在做一个用户注册的功能,除了用户名和年龄是必填项外,其他都是可选项,利用关键字参数来定义这个函数就能满足注册的需求。
和可变参数类似,也可以先组装出一个dict,然后,把该dict转换为关键字参数传进去:
def person(name,age,**kwargs):
print('name',name,'age',age,kwargs)
extra = {'city':'beijing','job':'Engineer'}
person('xiaoming',25,**extra)
运行结果为:
name xiaoming age 25 {'job': 'Engineer', 'city': 'beijing'}
6. 异常处理:
① 已知类型:try ... except
def calc(a,b):
try:
print(a/b)
except ZeroDivisionError:
print('除数不能为0!')
a = int(input('-'))
b = int(input('-'))
calc(a,b)
运行结果为:
-2
-0
除数不能为0!
② 未知类型:https://www.cnblogs.com/zln1021/p/6106185.html
def calc(a,b):
try:
print(a/b)
except Exception: # BaseException
print('除数不能为0!')
a = int(input('-'))
b = int(input('-'))
calc(a,b)
③ 多重异常:
def calc(a,b):
try:
print(a/b)
except NameError:
print('该对象未申明')
except ZeroDivisionError:
print('除数不能为0')
a = int(input('-'))
b = int(input('-'))
calc(a,b)
④ 最终处理:
def calc(a,b):
try:
print(a/b)
except NameError:
print('该对象未申明')
except ZeroDivisionError as msg:
# print(msg)
print('除数不能为0',msg)
finally:
print('程序执行完毕')
a = int(input('-'))
b = int(input('-'))
calc(a,b)
⑤ else:在程序没有抛出异常的时候,继续执行else语句
def calc(a,b):
try:
print(a/b)
except NameError:
print('该对象未申明')
except TypeError as msg:
print(msg)
else:
print('程序执行完毕!')
a = int(input('请输入第一个数:'))
b = int(input('请输入第二个数:'))
calc(a,b)
⑥抛出异常:异常必须为exception的子类
raise TypeError('类型错误')
def calc(a,b):
try:
print(a/b)
except NameError:
print('该对象未申明')
# 查看异常后不做处理继续抛出异常
raise
except ZeroDivisionError as msg:
# print(msg)
print('除数不能为0',msg)
else:
print('程序执行完毕')
a = int(input('-'))
b = int(input('-'))
calc(a,b)
⑦ 练习:name没有定义,type异常,并抛出是何种异常
def calc(a,b):
try:
print(a/b)
except NameError as msg:
print('该对象未申明',msg)
raise
except TypeError as msg:
print(msg)
raise
else:
print('程序执行完毕!')
a = int(input('请输入第一个数:'))
b = int(input('请输入第二个数:'))
calc(a,b)
7. 文件IO:
文件操作流程:
① 找到文件 :新建文件new --> file-->data.txt,查看文件路径:右键data,选择Show in Explorer(路径支持绝对路径和相对路径)
data文件内容如下:
a,b,c
tom,lucy,lily
1,2,3
② 打开文件:(文件路径和打开模式)
打开文件的模式有:
- r:只读模式(默认)。
- w:只写模式(不可读;不存在则创建;存在则删除内容)
- a:追加模式 -- append(可读;不存在则创建;存在则只追加内容)
"+" 表示可以同时读写某个文件
- r+:可读写文件(可读;可写;可追加)
- w+:写读
- a+:同a
f = open('F:CodeVIPtest2data.txt','r')
③ 操作文件:读、写
读取文件所有内容:print(f.read()) -- 文件大时不要用
读取指定长度字节的数据:print(f.read(4)) -- 读取前4个字节的内容
读取整行:print(f.readline()) -- 读取光标所在位置的整行
读取前5行:
for i in range(5):
print(f.readline())
如果需要读取5-10行,中间加个if判断即可
读取所有行:print(f.readlines()) -- 列表形式输出
运行结果:['a,b,c ', 'tom,lucy,lily ', '1,2,3 ', ' ']
写:
f = open('F:CodeVIPtest2data2.txt','r+')
f.write('hello python! ')
f.write('welcome~')
f.close()
④ 关闭文件:f.close()
作业:只取出data中的数字并写入另外的文件
思路:
① 读取文件中的所有数据 -- readlines
② 从列表中找出含有的数字
判断列表中的每一个元素是否含有数字 -- 将列表中的每一个元素(数据的行)取出来,作为一个小的列表
判断每一个小的列表是否含有数字 isdigit(),如果是数字,则追加到一个新的列表
③ 排序、写入
data:
a,b,c
tom,lucy,lily
1,3,9,6,8,4,5
代码:
f = open('F:CodeVIPtest2data.txt','r')
lines = f.readlines()
# print(lines)
lists = []
for l in lines:
# print(l)
s = l.split(',') # 切片
# print(s)
for m in s:
if m.strip().isdigit(): # 判断是否为数字
lists.append(m.strip())
else:
continue
for i in range(1,len(lists)): # 冒泡排序
for j in range(0,len(lists)-i):
if lists[j] > lists[j+1]:
lists[j],lists[j+1] = lists[j+1],lists[j]
print(lists)
f.close()
f1 = open('F:CodeVIPtest2data3.txt','r+')
f1.write(str(lists))
f1.close()
8. 模块和包:
① 模块:模块是一个包含所有你定义的函数和变量的文件,其后缀名是.py,模块可以被别的程序引入,以使用该模块中的函数等功能,这也是使用python标准库的方法。
Mymodule:
def fun1():
print('我是fun1函数')
def fun2():
print('我是fun2函数')
print('name的值为:',__name__)
# 每个模块都有一个__name__属性,当其值为:'__main__'时,表明该模块自身在运行,否则是被引入
if __name__ == '__main__':
fun1()
fun2()
__name__的作用:一个模块被另一个程序第一次引入时,其主程序将运行。如果我们想在模块被引入时,模块中的某一程序块不执行,我们可以用__name__属性来使该程序块仅在该模块自身运行时执行
② 包:当一个目录内含有__init__.py文件时,就可以视该目录为一个包。
③ 调用包和模块:
第一种调用方式:import 模块名/ 包名(只能导入名称)
右键practice-->mark directory as->resource root(将当前路径加入python查找的默认路径
如果通过import调用,使用包内的方法需要通过包名.函数名的形式
Mymodule.fun1()
第二种调用方式:from 包名 import 模块名
from ... import的形式导入,from后面只能跟包和模块名,不能跟函数名,import后面跟函数或者类名
绝对导入:from practice import module
from Mymodule import fun1
通过from-import的形式可以直接使用函数名
fun1()
fun2()
第三种调用方式:相对导入
from .database import Database # 点号表示使用当前路径的database模块
from ..database import Database # 使用两个点号表示访问上层的父类
第四种调用方式:通过import* 可以导入多个函数
from Mymodule import *
二、面向对象的类、属性、方法
1. 基础:
类:具有相同的特性,且能够完成某些动作的事物组成的一个集合
属性:类中的事物所具有的特性,趋于静态
方法:类中的事物所能够完成的动作或功能,趋于动态
实例/对象:类中某一个具体的对象或实例
实例化:定义类中某一个对象的过程
2. 类的定义:
class 类名(object):
属性
方法
注意:
① 属性和方法可以为空,里面直接写pass即可,表示是一个空类
② 方法一般都是动作,能完成某些功能,属性一般都是特点,静态,用来描述事物的特性
举例:
# 类的定义
class Person:
# 类属性/方法 -- 初始化方法,类中必须存在的且在实例化过程中自动被调用的方法(定义属性)
def __init__(self,name):
self.name = name
print('此方法被调用!')
def eat(self,food):
print('%s吃%s'%(self.name,food))
# print(self.sleep()) #调用别的方法需要加self
def sleep(self):
print('睡觉')
# 类的调用第一步:实例化(创建一个对象:变量名=类名())---是否需要传参就看__init__方法中除了self是否还有其他参数
a = Person('xiaoming')
b = Person('xiaohong')
# 类的调用第二步:调用类中的方法(实例名.方法名()) ---是否需要传参就看该方法中除了self是否还有其他参数
a.eat('rice')
b.eat('noodle')
运行结果为:
此方法被调用!
此方法被调用!
xiaoming吃rice
xiaohong吃noodle
3. 类的实例化:
变量=类名('xx') ---是否需要传参就看__init__方法中除了self是否还有其他参数
4. 类中方法的调用:
实例名.方法名('xx') ---是否需要传参就看该方法中除了self是否还有其他参数
练习:
① 定义一个学生类:Student、内部含有一个方法:study,实现打印:小明学习xx课程
class person():
def __init__(self,name):
self.name = name
def study(self,course):
print('%s学习%s'%(self.name,course))
a = person('xiaoming')
a.study('math')
运行结果为:
xiaoming学习math
② 定义一个类名:Student—学生、类内部含有一个属性:sno—学号,一个方法:study—学习,实现打印:学号为xx的学生,学习xx课程
class Student():
def __init__(self,sno):
self.sno = sno
def study(self,course):
print('学号为%s的学生,学习%s的课程'%(self.sno,course))
a = Student('6')
a.study('math')
运行结果为:
学号为6的学生,学习math的课程
5. 继承:为了提高代码的复用性,可以通过继承来减少属性和方法的编写
语法:继承谁就在括号中写谁-类名
注意事项:
① 继承后,子类就具有父类的所有属性和方法,但是父类不能具备子类的属性和方法
② 如果父类中没有子类需要的方法,可以在子类中自行定义
③ 实例化和调用方法的时候要区分是否需要传参
④ 继承的时候需要用到父类的属性时,需要在子类中再次进行初始化
例子:
class Animal:
def eat(self):
print('吃饭')
def drink(self):
print('喝水')
class Dog:
def eat(self):
print('吃饭')
def drink(self):
print('喝水')
class Dog(Animal): # 继承
def bark(self):
print('汪汪叫')
class Cat(Animal):
def catch(self):
print('抓老鼠')
a = Cat()
a.eat()
运行结果:
吃饭
练习:
定义一个Teacher类,继承Person类,拥有自身的属性工号gh,自身的方法:teach教课(课程);
① 实现gh为xx的老师,教xx课
② 实现gh为xx老师,在xx上班,一月工资xx
③ 名字是xx,工号为xx的老师,吃饭
class Person:
def __init__(self,name):
self.name = name
print('此方法被调用!')
def eat(self,food):
print('%s吃%s'%(self.name,food))
def sleep(self):
print('睡觉')
class Teacher(Person):
def __init__(self,gh,salary,name):
self.gh = gh
self.salary = salary
self.name = name
def teach(self,course):
print('工号为%s的老师,教%s课'%(self.gh,course))
def address(self,place):
print('工号为%s的老师,在%s上班,一月薪资%s'%(self.gh,place,self.salary))
def eat(self,food):
print('名字是%s,工号为%s的老师吃%s'%(self.name,self.gh,food))
a = Person('xiaoming')
b = Person('xiaohong')
c = Teacher('66','20000','梁老师')
a.eat('rice')
b.eat('noodle')
c.teach('math')
c.address('beijing')
c.eat('rice')
运行结果为:
此方法被调用!
此方法被调用!
xiaoming吃rice
xiaohong吃noodle
工号为66的老师,教math课
工号为66的老师,在beijing上班,一月薪资20000
名字是梁老师,工号为66的老师吃rice
6.重写:当继承的父类方法不满足自身需要的时候,我们可以重写该父类的方法,注意,必须同名
例子:
class Animal:
def eat(self):
print('吃饭')
def drink(self):
print('喝水')
class Dog(Animal):
def bark(self):
print('汪汪叫')
class Xiaotq(Dog):
def fly(self):
print('飞翔')
def bark(self):
print('哮天犬狂叫')
a = Xiaotq()
a.fly()
a.bark()
调用父类的方法:
class Animal:
def eat(self):
print('吃饭')
def drink(self):
print('喝水')
class Dog(Animal):
def bark(self):
print('汪汪叫')
class Xiaotq(Dog):
def fly(self):
print('飞翔')
def bark(self):
print('哮天犬狂叫')
# 第一种调用被重写的方法,父类的名字.方法名()
Dog.bark()
# 第二种
super().bark()
a = Xiaotq()
a.fly()
a.bark()
# 子类可以拥有父类的功能
a.eat()
多重继承的注意事项:
# 尽可能不要出现相同的方法名字
class Base(object):
def test(self):
print('------base')
class A(Base):
def test1(self):
print('------test1')
class B(Base):
def test2(self):
print('------test2')
class C(A,B):
pass
# 方法的查找顺序是按照继承的最近来,先查找自身,再查找A,再查找B,再查找Base
c = C()
c.test()
c.test1()
c.test2()
7.多态:多态性是指具有不同功能的函数可以使用相同的函数名,这样就可以用一个函数名调用不同内容的函数。在面向对象方法中一般是这样表述多态性:向不同的对象发送同一条消息,不同的对象在接收时会产生不同的行为(即方法)。也就是说,每个对象可以用自己的方式去响应共同的消息。所谓消息,就是调用函数,不同的行为就是指不同的实现,即执行不同的函数。
class Dog(object):
def print_self(self):
print('大家好,我是xxx')
class Xiaotq(Dog):
def print_self(self):
print('hello,everyboby,我是xxx')
def introduce(temp):
temp.print_self()
dog1 = Dog()
dog2 = Xiaotq()
# 多态的关键在于,同样是调用相同的方法,但是完成的内容却不同,普通狗的自我介绍是与哮天犬的自我介绍不一样
introduce(dog1)
introduce(dog2)
8.私有属性和私有方法
类的私有属性
__abc:两个下划线开头,声明该属性为私有,不能在类的外部被使用或直接访问。在类内部的方法中使用时 self.__abc。
类的方法
在类的内部,使用 def 关键字来定义一个方法,与一般函数定义不同,类方法必须包含参数 self,且为第一个参数,self 代表的是类的实例。
self 的名字并不是规定死的,也可以使用 this,但是最好还是按照约定是用 self。
类的私有方法
__method:两个下划线开头,声明该方法为私有方法,只能在类的内部调用 ,不能在类的外部调用。self.__ methods。
# 如果调用的是继承父类中的公有方法,可以在这个公有方法中访问父类中的私有属性和私有方法
# 但是如果在子类中实现了一个公有方法,那么这个方法是不能够调用继承的父类中的私有方法和私有属性的
class A:
def __init__(self):
self.num1 = 100
self.__num2 = 200
# print(self.num1,self.__num2)
def test1(self):
print('公有方法')
def __test2(self):
print('私有方法')
def test3(self):
print('公有方法中调用私有方法和私有属性')
self.__test2()
print(self.num1)
print(self.__num2)
class B(A):
def test4(self):
# self.__num2
self.__test2()
b = B()
b.test4()
Python练习题:
1.打印小猫爱吃鱼,小猫要喝水
class Animal():
def __init__(self,name):
self.name = name
print('此方法被调用')
def eat(self,food):
print('%s爱吃%s'%(self.name,food))
def drink(self,drinks):
print('%s要喝%s'%(self.name,drinks))
a = Animal('小猫')
a.eat('鱼')
a.drink('水')
2.小明爱跑步,爱吃东西。
① 小明体重75.0公斤
② 每次跑步会减肥0.5公斤
③ 每次吃东西体重会增加1公斤
④ 小美的体重是45.0公斤
class Person:
def __init__(self,name,weight):
self.name = name
self.weight = weight
print('此方法被调用')
def person1(self):
print('%s的体重是%s'%(self.name,self.weight))
def run(self):
print('%s爱跑步,每次跑步会减肥%s'%(self.name,self.weight))
def eat(self,food):
print('%s爱吃%s,每次吃东西体重会增加%s'%(self.name,food,self.weight))
def person2(self):
print('%s的体重是%s'%(self.name,self.weight))
a = Person('小明','75kg')
b = Person('小明','0.5kg')
c = Person('小明','1kg')
d = Person('小美','45kg')
a.person1()
b.run()
c.eat('东西')
d.person2()
运行结果为:
此方法被调用
此方法被调用
此方法被调用
此方法被调用
小明的体重是75kg
小明爱跑步,每次跑步会减肥0.5kg
小明爱吃东西,每次吃东西体重会增加1kg
小美的体重是45kg
3.摆放家具
需求:
① 房子有户型,总面积和家具名称列表,新房子没有任何的家具
② 家具有名字和占地面积,其中
床:占4平米
衣柜:占2平面
餐桌:占1.5平米
③将以上三件家具添加到房子中
④打印房子时,要求输出:户型,总面积,剩余面积,家具名称列表
class HouseItem():
def __init__(self, name, area):
self.name = name
self.area = area
def __str__(self):
return '[%s]占地 %.2f' % (self.name, self.area)
class House():
def __init__(self, house_type, area):
self.house_type = house_type
self.area = area # 剩余面积
self.free_area = area
self.item_list = []
def __str__(self):
return ('户型:%s 总面积:%.2f[剩余:%.2f] 家具:%s' % (self.house_type, self.area, self.free_area, self.item_list))
def add_item(self, item):
# 1.判断家具的面积
if item.area > self.free_area:
print('%s的面积太大,无法添加' % item.name)
# 2.将家具的名称添加到列表中
self.item_list.append(item.name)
# 3.计算剩余面积
self.free_area -= item.area
# 1.创建家具对象
bed = HouseItem('bed', 4)
yg = HouseItem('yg', 2)
table = HouseItem('table', 1.5)
# 2.创建房子对象
my_house = House('两室一厅', 100)
# 3.添加家具
my_house.add_item(bed)
my_house.add_item(yg)
my_house.add_item(table)
print(my_house)
运行结果为:
户型:两室一厅
总面积:100.00[剩余:92.50]
家具:['bed', 'yg', 'table']
4.士兵开枪
需求:
① 士兵瑞恩有一把AK47
② 士兵可以开火(士兵开火扣动的是扳机)
③ 枪 能够 发射子弹(把子弹发射出去)
④ 枪 能够 装填子弹 --增加子弹的数量
class Soldier:
def __init__(self, name):
self.name = name
self.gun = None
def __str__(self):
return '%s士兵的枪为%s' % (self.name, self.gun)
def fire(self):
if self.gun == None:
print('士兵还没有枪')
else:
self.gun.shoot()
class Gun:
def __init__(self, model):
self.model = model
self.bullet_count = 0
def __str__(self):
return '%s的子弹有%s颗' % (self.model,self.bullet_count)
def shoot(self):
if self.bullet_count < 1:
print('没有子弹了,请补充子弹再射击')
else:
self.bullet_count -= 1
return self.bullet_count
def add_bullet(self, count):
if self.bullet_count >= 50:
print('子弹已经装满,不可再加')
else:
self.bullet_count += count
ryan = Soldier('Ryan')
AK47 = Gun('AK47')
AK47.shoot() # 此时没有子弹不能射击
AK47.add_bullet(50) # 加50发子弹
AK47.shoot()
print(AK47)
ryan.gun = AK47
ryan.fire()
print(ryan)
print(AK47)
运行结果为:
没有子弹了,请补充子弹再射击
AK47的子弹有49颗
Ryan士兵的枪为AK47的子弹有48颗
AK47的子弹有48颗