Python学习笔记_2

一、函数

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:\Code\VIPtest2\data.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\n', 'tom,lucy,lily\n', '1,2,3\n', '\n']

写:

f = open('F:\Code\VIPtest2\data2.txt','r+')
f.write('hello python!\n')
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:\Code\VIPtest2\data.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:\Code\VIPtest2\data3.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,实现打印:小明学***课程

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的学生,学***课程

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\n总面积:%.2f[剩余:%.2f]\n家具:%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颗

 

posted @ 2019-05-14 17:50  简单安安静  阅读(376)  评论(0编辑  收藏  举报