python开发---》C语言十分重要
高级语言 --》字节码
低级语言 --》机器码
PHP类:适用于写网页,局限性
python java: 可以写网页,也可以写后台功能
- python 执行效率低,开发效率高
- java 执行效率高,开发效率低
各种语言差异十分小
Python软件--》Python解释器(内存管理)
Python 种类:
Python 指代CPython
JPython --》Java --》C
Pypy 用CPython 开发的Python,,比CPython更快,直接转换成机器码
....
a. python基础
- 基础
- 基本数据类型
- 函数
- 面向对象
b.网络编程
c.WEB框架
用于写网站
d.设计模式(十分重要) + 算法
e.项目阶段
python中文编码
# -*- coding;utf8 -*-
Python3 默认使用utf-8编码
Python 中定义变量不需要指定类型,而在其他高级语言都需要。
用type可以查看变量的类型:
name = '小明'
age = 28
sex = True
weight = 120.0
print(type(name)) //
print(type(age)) //
print(type(sex)) //
print(type(weight)) //
在Python3里,只有一种整数类型int,大多数情况下,和Python2中的长整型类似。
print(type(2*65)) // ,
在Python中,bool类型参与运算时,True为1,False为0。
a = 10
b = 1.05
c = True
print(a + b + c) // 12.05
数字和字符串相加时是不会将数字自动转换为字符串的,这一点我之前没注意到。
s = "李白"
a = 100
print(a + s) // 报错 TypeError: unsupported operand type(s) for +: 'int' and 'str'
input() 键盘输入,用户输入的任何内容 Python 都认为是一个字符串。
password = input("请输入password")
print(type(password)) //
Python输出不换行
print("****", end="")
完整的九九乘法表
row = 0
while row < 9:
row = row + 1
col = 0
while col < row:
col = col + 1
print("%d * %d = %2d " %(col, row, row*col), end="")
print("")
打印结果:
1 * 1 = 1
1 * 2 = 2 2 * 2 = 4
1 * 3 = 3 2 * 3 = 6 3 * 3 = 9
1 * 4 = 4 2 * 4 = 8 3 * 4 = 12 4 * 4 = 16
1 * 5 = 5 2 * 5 = 10 3 * 5 = 15 4 * 5 = 20 5 * 5 = 25
1 * 6 = 6 2 * 6 = 12 3 * 6 = 18 4 * 6 = 24 5 * 6 = 30 6 * 6 = 36
1 * 7 = 7 2 * 7 = 14 3 * 7 = 21 4 * 7 = 28 5 * 7 = 35 6 * 7 = 42 7 * 7 = 49
1 * 8 = 8 2 * 8 = 16 3 * 8 = 24 4 * 8 = 32 5 * 8 = 40 6 * 8 = 48 7 * 8 = 56 8 * 8 = 64
1 * 9 = 9 2 * 9 = 18 3 * 9 = 27 4 * 9 = 36 5 * 9 = 45 6 * 9 = 54 7 * 9 = 63 8 * 9 = 72 9 * 9 = 81
字符串一旦创建,就不可修改,一旦修改或者拼接,都会造成重新生成字符串,Python3 的 range 默认就是一个生成器
模块名也是一个标识符
标示符可以由 字母、下划线 和 数字 组成
不能以数字开头
不能与关键字重名
注意:如果在给 Python 文件起名时,以数字开头 是无法在 PyCharm 中通过导入这个模块的
.Pyc 文件
C 是 compiled 编译过 的意思
操作步骤:
浏览程序目录会发现一个 __pycache__ 的目录,
目录下会有一个以导入文件名模块.cpython-36.pyc 文件,cpython-36 表示 Python 解释器的版本,
这个 pyc 文件是由 Python 解释器将 模块的源码 转换为 字节码,
Python 这样保存字节码是作为一种启动速度的优化
字节码
Python 在解释源程序时是分成两个步骤的
首先处理源代码,编译生成一个二进制 字节码,
再对 字节码 进行处理,才会生成 CPU 能够识别的机器码,
有了模块的字节码文件之后,下一次运行程序时,如果在上次保存字节码之后没有修改过源代码,
Python 将会加载 .pyc 文件并跳过编译这个步骤
当 Python 重编译时,它会自动检查源文件和字节码文件的时间戳,
如果你又修改了源代码,下次程序运行时,字节码将自动重新创建
Python 对 list 的操作,列表可以存储不同类型的数据
| 序号 | 分类 | 关键字 / 函数 / 方法 | 说明 |
1 | 增加 | 列表.insert(索引, 数据) | 在指定位置插入数据 |
| | 列表.append(数据) | 在末尾追加数据
| | 列表.extend(列表2) | 将列表2 的数据追加到列表 |
2 | 修改 | 列表[索引] = 数据 | 修改指定索引的数据 |
3 | 删除 | del 列表[索引] | 删除指定索引的数据 |
| | 列表.remove[数据] | 删除第一个出现的指定数据 |
| | 列表.pop | 删除末尾数据 |
| | 列表.pop(索引) | 删除指定索引数据 |
| | 列表.clear | 清空列表 |
4 | 统计 | len(列表) | 列表长度 |
| | 列表.count(数据) | 数据在列表中出现的次数 |
5 | 排序 | 列表.sort() | 升序排序 |
| | 列表.sort(reverse=True) | 降序排序 |
| | 列表.reverse() | 逆序、反转 |
[1,2] + [3,4] = [1, 2, 3, 4]
注意 extend 和 append 的区别
l = [1, 2]
l.extend([3,4])
print(l) // [1, 2, 3, 4]
l.append([5,6])
print(l) // [1, 2, 3, 4, [5, 6]]
list[0::-1] 中间的那个参数不写,表示-无穷,第三个参数为步长
注意一下问题:
test_list = ['1', '1', '23', '23', '5', '56']
for i in test_list:
if i == "1":
test_list.remove(i)
print(test_list)
连续的两个 '1' ,第二个无法删除
结果:['1', '23', '23', '5', '56']
Python 的元组,可以存储相同的数,唯一的是不能修改
Tuple(元组)与列表类似,不同之处在于元组的元素不能修改,
元组 表示多个元素组成的序列,
在 Python 开发中,有特定的应用场景
用于存储 一串 信息,数据 之间使用 , 分隔
元组用 () 定义
元组的 索引 从 0 开始
索引 就是数据在 元组 中的位置编号
python info_tuple = ("zhangsan", 18, 1.75)
创建空元组
python info_tuple = ()
元组中 只包含一个元素 时,需要 在元素后面添加逗号
python info_tuple = (50, )
single_tuple = (123)
print(type(single_tuple)) //
(1,2) + (3,4) = (1, 2, 3, 4)
格式字符串,格式化字符串后面的 () 本质上就是一个元组
single_tuple = ("libai", 28)
s = "my name is %s, age is %d" %single_tuple
print(s) // my name is libai, age is 28
列表和元组的相互转换
使用 list 函数可以把元组转换成列表
list(元组)
使用 tuple 函数可以把列表转换成元组
tuple(列表)
set 集合
set 的数据中顺序不定,可求交、并、差集 set1&set2、set1|set2、set1-set2、
在Python中,字符串的单引号和双引号的作用是一样的
字符串的方法:字符串中的方法都是不修改原来字符串的内容,而是返回一个新的字符串
字符串的替换,replace方法执行完成之后,会返回一个新的字符串,而不会对原有字符串进行修改
string = "hello world"
print(string.replace("world", "python")) // hello python
print(string) // hello world
replace方法执行完成之后,会返回一个新的字符串
注意:不会修改原有字符串的内容
for 循环可以和 else 配合使用
l = [1, 2, 3, 4]
for i in l:
print(i)
if(i == 2):
break
else:
# 如果循环体内部使用了break退出了循环,那么else下方的代码就会被执行
print("for ending")
in、 not in
name = '李白'
if "白" in name:
print("come in ")
else:
print("not in")
在python3 中无长整型,也就是Long
格式化占位符
#用字符标识
a = 'i am {name}, age {age}'
print(a)
b = a.format(name='libai', age=20)
print(b)
输出结果:
i am {name}, age {age}
i am libai, age 20
#用数字标识,从0开始
a = 'i am {0}, age {1}'
print(a)
b = a.format('libai', 20)
print(b)
输出结果:
i am {0}, age {1}
i am libai, age 20
可变类型和不可变类型
不可变类型,内存中的数据不允许被修改:
数字类型:int、bool、float、complex、long
字符串:str
元组:tuple
可变类型,内存中的数据可以被修改:
列表:list
字典:dict
注意
可变类型的数据变化,是通过 方法 来实现的,
如果给一个可变类型的变量,赋值了一个新的数据,引用会修改
变量不再对之前的数据引用,变量改为对新赋值的数据引用
!!!可变类型的数据不可以作为字典的key,会报错unhashable type: 'list' // 'dict'
Python中的哈希 (hash)
Python 中内置有一个名字叫做 hash(o) 的函数,
接收一个不可变类型的数据作为参数,返回结果是一个整数,
哈希是一种算法,其作用就是提取数据的 特征码(指纹),
相同的内容得到相同的结果,
不同的内容得到不同的结果,
对于字典中:
在 Python 中,设置字典的 键值对 时,会首先对 key 进行 hash 以决定如何在内存中保存字典的数据
以方便 后续 对字典的操作:增、删、改、查
键值对的 key 必须是不可变类型数据
键值对的 value 可以是任意类型的数据
要修改全局变量的值,需要在函数内部使用global声明一下变量,即可修改
对于函数的参数
不可变和可变的参数
问题 1:在函数内部,针对参数使用赋值语句,会不会影响调用函数时传递的实参变量?
—— 不会!无论传递的参数是可变还是不可变,只要针对参数使用赋值语句,
会在函数内部修改局部变量的引用,不会影响到外部变量的引用
例子:
def func(num, num_list):
num = 1
num_list = ["a", "b", "c"]
return num,num_list
num = 200
num_list = [1, 2, 3]
func(num, num_list)
print(num) // 200
print(num_list) // [1, 2, 3]
问题 2:如果传递的参数是可变类型,在函数内部,使用方法修改了数据的内容,会不会影响到外部的数据?
—— 会!
例子:
def func(num_list):
num_list.append("a")
return num_list
num_list = [1, 2, 3]
func(num_list)
print(num_list) // [1, 2, 3, 'a']
缺省参数的定义位置
必须保证带有默认值的缺省参数在参数列表末尾。
Python 支持函数传递多值参数
定义支持多值参数的函数
有时可能需要 一个函数 能够处理的参数 个数 是不确定的,这个时候,就可以使用 多值参数
Python 中有 两种 多值参数:
参数名前增加 一个 * 可以接收 元组
参数名前增加 两个 * 可以接收 字典
一般在给多值参数命名时,习惯使用以下两个名字
*args —— 存放 元组 参数,前面有一个 *
**kwargs —— 存放 字典 参数,前面有两个 *
args 是 arguments 的缩写,有变量的含义
kw 是 keyword 的缩写,kwargs 可以记忆 键值对参数
例子:
def demo(num, *args, **kwargs):
print(num)
print(args)
print(kwargs)
demo(1, 2, 3, 4, 5, name="小明", age=18, gender=True)
# demo(1, 2, 3, 4, 5, name="小明", age=18, gender=True, 66) 这样写会报参数错误
打印:
1
(2, 3, 4, 5)
{'name': '小明', 'age': 18, 'gender': True}
两个小例子
def demo(args):
sum = 0
for a in args:
sum = sum + a
return sum
print(demo((1, 2, 3, 4, 5))) // 15
def demo(*args):
sum = 0
for a in args:
sum = sum + a
return sum
print(demo(1, 2, 3, 4, 5)) // 15
元组和字典的拆包
* 在调用带有多值参数的函数时,如果希望:
* 将一个元组变量,直接传递给 `args`
* 将一个字典变量,直接传递给 `kwargs`
* 就可以使用拆包,简化参数的传递,拆包的方式是:
* 在元组变量前,增加一个`*`
* 在字典变量前,增加两个`*`
def demo(*args, **kwargs):
print(args)
print(kwargs)
# 需要将一个元组变量/字典变量传递给函数对应的参数
gl_nums = (1, 2, 3)
gl_xiaoming = {"name": "小明", "age": 18}
# 会把 num_tuple 和 xiaoming 作为元组传递个 args
demo(gl_nums, gl_xiaoming)
打印:
((1, 2, 3), {'name': '小明', 'age': 18})
{}
demo(*gl_nums, **gl_xiaoming)
打印:
(1, 2, 3)
{'name': '小明', 'age': 18}
Python 的递归求和
def func(num):
if num == 1:
return 1
return num + func(num-1)
print(func(100)) // 5050
Python 的类 面向对象
相比较函数,面向对象是更大的封装,根据职责在一个对象中封装多个方法
在完成某一个需求前,首先确定职责 —— 要做的事情(方法)
根据职责确定不同的对象,在对象内部封装不同的方法(多个)
最后完成的代码,就是顺序地让不同的对象调用不同的方法即可
注重 对象和职责,不同的对象承担不同的职责
更加适合应对复杂的需求变化,是专门应对复杂项目开发,提供的固定套路
Python 的内置函数,可以使用 dir() 查看
在 Python 中 对象几乎是无所不在的,变量、数据、函数都是对象
使用内置函数 dir 传入 标识符数据,可以查看对象内的所有属性及方法,
提示 __方法名__ 格式的方法是 Python 提供的内置方法/属性
1. 初始化方法 init
当使用 类名() 创建对象时,会自动执行以下操作:
为对象在内存中分配空间 —— 创建对象 __new__
为对象的属性设置初始值 —— 初始化方法 __init__
这个初始化方法就是 __init__ 方法,__init__ 是对象的内置方法
__init__ 方法是专门用来定义一个类具有哪些属性的方法!
class Cat:
def __init__(self):
print("初始化方法")
tom = Cat() // 控制台会打印出 初始化方法 字段
2. del 方法
在 Python 中当使用 类名() 创建对象时,为对象分配完空间后,自动调用 __init__ 方法
当一个 对象被从内存中销毁前,会自动 调用 __del__ 方法
__init__ 改造初始化方法,可以让创建对象更加灵活
__del__ 如果希望在对象被销毁前,再做一些事情,可以考虑一下 __del__ 方法
生命周期
一个对象从调用 类名() 创建,生命周期开始
一个对象的 __del__ 方法一旦被调用,生命周期结束
在对象的生命周期内,可以访问对象属性,或者让对象调用方法
3.str 方法
在 Python 中,使用 print 输出 对象变量,默认情况下,
会输出这个变量引用的对象是由哪一个类创建的对象,以及在内存中的地址(十六进制表示)
如果在开发中,希望使用 print 输出对象变量时,能够打印自定义的内容,
就可以利用 __str__ 这个内置方法了
注意:__str__ 方法必须返回一个字符串
Python 的身份运算符 is,is not
私有属性和私有方法,外界无法直接访问到,子类同样无法放访问
在实际开发中,对象的某些属性或方法可能只希望在对象的内部被使用,而不希望在外部被访问到
私有属性就是对象不希望公开的属性
私有方法就是对象不希望公开的方法
定义方式
在定义属性或方法时,在属性名或者方法名前增加两个下划线,定义的就是私有属性或方法
伪私有属性和私有方法,Python 中,并没有真正意义的私有
提示:在日常开发中,不要使用这种方式,访问对象的 私有属性 或 私有方法
Python 中,并没有真正意义的私有
在给属性、方法命名时,实际是对名称做了一些特殊处理,使得外界无法访问到
处理方式:在名称前面加上 _类名 => _类名__名称 即可访问
对于子类:
子类对象不能在自己的方法内部,直接访问父类的私有属性或私有方法
子类对象可以通过父类的公有方法,间接访问到私有属性或私有方法
多继承
子类可以拥有多个父类,并且具有所有父类的 属性 和 方法
Python 中的 MRO —— 方法搜索顺序
Python 中针对 类 提供了一个 内置属性 __mro__ 可以查看方法搜索顺序
MRO 是 method resolution order,主要用于在多继承时判断方法、属性的调用路径
在搜索方法时,是按照 __mro__ 的输出结果 从左至右 的顺序查找的
如果在当前类中找到方法,就直接执行,不再搜索
如果没有找到,就查找下一个类中是否有对应的方法,如果找到,就直接执行,不再搜索
如果找到最后一个类,还没有找到方法,程序报错
object 是 Python 为所有对象提供的 基类,提供有一些内置的属性和方法,可以使用 dir 函数查看
新式类:以 object 为基类的类,推荐使用
经典类:不以 object 为基类的类,不推荐使用
在 Python 3.x 中定义类时,如果没有指定父类,会默认使用 object 作为该类的基类
—— Python 3.x 中定义的类都是 新式类
在 Python 2.x 中定义类时,如果没有指定父类,则不会以 object 作为基类
新式类 和 经典类 在多继承时 —— 会影响到方法的搜索顺序
为了保证编写的代码能够同时在 Python 2.x 和 Python 3.x 运行!
今后在定义类时,如果没有父类,建议统一继承自 object
子类使用父类方法,必须传入self
继承,子类继承父类
class man:
def __init__(self, name, gender):
self.name = name
self.gender = gender
def head(self):
print('this is man head function')
class student(man):
# 子类可以再定义,定义重复会使用子类方法,如 init
def __init__(self, id, name, gender):
super().__init__(name, gender)
self.id = id
s = student('15040', 'libai', '男')
print(s.__dict__)
s.head()
输出结果:
{'name': 'libai', 'gender': '男', 'id': '15040'}
this is man head function
接口继承,规定在子类中必须重新定义某些方法,如下面的 others
class man(metaclass=abc.ABCMeta):
def __init__(self, name, gender):
self.name = name
self.gender = gender
@abc.abstractmethod # 要求必须在子类中定义others方法,没定义不能实例化
def others(self):
print('this is others')
class student(man): # 继承父类
# 子类可以再定义,定义重复会使用子类方法
def __init__(self, id, name, gender):
super().__init__(name, gender)
self.id = id
def others(self): # 必须定义others
print('son define others function')
s = student('15040', 'libai', '男')
print(s.__dict__)
s.others()
输出结果:
{'name': 'libai', 'gender': '男', 'id': '15040'}
son define others function
面向对象三大特性
封装:
根据职责将属性和方法封装到一个抽象的类中,定义类的准则
在python中,没有定义完全意义上的封装
第一个层面的封装:类就是麻袋,这本身就是一种封装
第二个层面的封装:类中定义私有的,只在类的内部使用,外部无法访问
第三个层面的封装:明确区分内外,内部的实现逻辑,外部无法知晓,
并且为封装到内部的逻辑提供一个访问接口给外部使用(这才是真正的封装)
继承:
实现代码的重用,相同的代码不需要重复的编写,
设计类的技巧,子类针对自己特有的需求,编写特定的代码
多态:
不同的子类对象调用相同的父类方法,产生不同的执行结果
不同的对象调用相同的方法,执行的逻辑并不一样
类的继承有两层意义,1.改变,2,扩展
多态就是类的这两层意义的一个具体的实现机制
即,调用不同的类实例化的对象下的相同方法,实现的过程不一样
多态可以增加代码的灵活度,以继承和重写父类方法为前提,
是调用方法的技巧,不会影响到类的内部设计
通俗点来说,子类重写了就调用之类的方法,子类没有重写就调用父类的方法,这就是多态
封装例子,设定封装的外部接口
class test:
def __init__(self, name, gender):
self.__name = name #封装
self.gender = gender
def get_name(self): #外部访问内部封装变量的接口
return self.__name #内部访问隐藏变量不受影响
t = test('libai', '男')
print(test.__dict__)
print(t.__dict__)
print(t._test__name) #外部可以通过添加类名访问
print(t.get_name())
输出结果:
{'__module__': '__main__', '__init__': , 'get_name': , '__dict__': , '__weakref__': , '__doc__': None}
{'_test__name': 'libai', 'gender': '男'}
libai
libai
Python的类方法、静态方法、实例方法、@property装饰器
1. 类方法
在类方法内部可以直接访问类属性或者调用其他的类方法,
在方法内部,可以通过 cls. 访问类的属性,也可以通过 cls. 调用其他的类方法
@classmethod
def 类方法名(cls):
pass
例子:
class Test:
def __init__(self, x, y):
self.x = x
self.y = y
@classmethod
def ggg(cls):
print(cls)
t = Test(5,8)
t.ggg()
输出结果:
2. 静态方法
在开发时,如果需要在类中封装一个方法,这个方法:
既不需要访问实例属性或者调用实例方法,也不需要访问类属性或者调用类方法,
这个时候,可以把这个方法封装成一个 静态方法
@staticmethod
def 静态方法名():
pass
例子:
class Test:
def __init__(self):
print("初始化方法")
@staticmethod
def xxx(a,b):
return a + b
t = Test()
print(t.xxx(1, 8))
输出结果:
9
3. @property装饰器就是负责把一个方法变成属性调用的:
class tests:
def __init__(self, x, y):
self.x = x
self.y = y
@property
def sum(self):
print('x*y = %s' %(self.x+self.y))
test = tests(5,8)
test.sum
输出结果:
x*y = 13
总结:
实例方法 —— 方法内部需要访问 实例属性,由对象调用,至少一个self参数;执行实例方法时,自动将调用该方法的对象赋值给self;
实例方法 内部可以使用 类名. 访问类属性
类方法 —— 方法内部只需要访问 类属性,由对象调用,至少一个self参数;执行实例方法时,自动将调用该方法的对象赋值给self;
静态方法 —— 方法内部,不需要访问 实例属性 和 类属性,由类调用;无默认参数;
对比
相同点:对于所有的方法而言,均属于类,所以 在内存中也只保存一份
不同点:方法调用者不同、调用方法时自动传入的参数不同。
Python 中的单例 —— 让类创建的对象,在系统中只有唯一的一个实例
class MusicPlayer:
instance = None
def __new__(cls, *args, **kwargs):
# 1. 创建对象时,new方法会自动调用
print("__new__ function")
# 2. 为对象分配空间
if cls.instance is None:
cls.instance = super().__new__(cls)
print("获取到对象空间地址")
# 3. 返回对象的引用
return cls.instance
def __init__(self):
print("__init__ 初始化函数")
player1 = MusicPlayer()
print(player1)
player2 = MusicPlayer()
print(player2)
打印结果:
__new__ function
获取到对象空间地址
__init__ 初始化函数
<__main__.MusicPlayer object at 0x0000016BEAF0AB70>
__new__ function
获取到对象空间地址
__init__ 初始化函数
<__main__.MusicPlayer object at 0x0000016BEAF0AB70>
在上面的代码中,每次执行完new方法后,init方法也会执行一次,修改代码,使得只执行一次初始化工作
在每次使用 类名() 创建对象时,Python 的解释器都会自动调用两个方法:
__new__ 分配空间
__init__ 对象初始化
在上面对 __new__ 方法改造之后,每次都会得到第一次被创建对象的引用,但初始化方法还会被再次调用
需求:让初始化动作只被 执行一次
解决办法
定义一个类属性 init_flag 标记是否 执行过初始化动作,初始值为 False
在 __init__ 方法中,判断 init_flag,如果为 False 就执行初始化动作
然后将 init_flag 设置为 True
这样,再次 自动 调用 __init__ 方法时,初始化动作就不会被再次执行 了
class MusicPlayer:
instance = None
init_flag = False
def __new__(cls, *args, **kwargs):
# 1. 创建对象时,new方法会自动调用
print("__new__ function")
# 2. 为对象分配空间
if cls.instance is None:
cls.instance = super().__new__(cls)
print("获取到对象空间地址")
# 3. 返回对象的引用
return cls.instance
def __init__(self):
if self.init_flag:
return
print("__init__ 初始化函数")
self.init_flag = True
player1 = MusicPlayer()
print(player1)
player2 = MusicPlayer()
print(player2)
打印结果:
__new__ function
获取到对象空间地址
__init__ 初始化函数
<__main__.MusicPlayer object at 0x0000026114DBAB70>
__new__ function
获取到对象空间地址
<__main__.MusicPlayer object at 0x0000026114DBAB70>
Python 的异常机制
try:
# 尝试执行的代码
pass
except 错误类型1:
# 针对错误类型1,对应的代码处理
pass
except 错误类型2:
# 针对错误类型2,对应的代码处理
pass
except (错误类型3, 错误类型4):
# 针对错误类型3 和 4,对应的代码处理
pass
except Exception as result:
# 打印错误信息
print(result)
else:
# 没有异常才会执行的代码
pass
finally:
# 无论是否有异常,都会执行的代码
print("无论是否有异常,都会执行的代码")
else 只有在没有异常时才会执行的代码
finally 无论是否有异常,都会执行的代码
小例子:
try:
num = int(input("请输入整数:"))
result = 8 / num
print(result)
except ValueError:
print("请输入正确的整数")
except ZeroDivisionError:
print("除 0 错误")
except Exception as result:
print("未知错误 %s" % result)
else:
print("正常执行")
finally:
print("执行完成,但是不保证正确")
抛出自定义异常
def input_password():
# 1. 提示用户输入密码
pwd = input("请输入密码:")
# 2. 判断密码长度,如果长度 >= 8,返回用户输入的密码
if len(pwd) >= 8:
return pwd
# 3. 密码长度不够,需要抛出异常
# 1> 创建异常对象 - 使用异常的错误信息字符串作为参数
ex = Exception("密码长度不够")
# 2> 抛出异常对象
raise ex
try:
user_pwd = input_password()
print(user_pwd)
except Exception as result:
print("发现错误:%s" % result)
Python 导入模块
import 模块名1 as 模块别名
Python 操作文件
1、w 写模式,它是不能读的,如果用w模式打开一个已经存在的文件,会清空以前的文件内容,重新写
w+ 是读写内容,只要沾上w,肯定会清空原来的文件
2、r 读模式,只能读,不能写,而且文件必须存在
r+ 是读写模式,只要沾上r,文件必须存在
3、a 追加模式,也能写,在文件的末尾添加内容
4、rb+、wb+、ab+,这种是二进制模式打开或者读取,一些音乐文件
python3中的默认的编码解码方式为utf-8,而windows默认使用的编码方式为gbk
当读取一个windows文件(gbk),可以指定读取时使用的编码encoding=('gbk')或者不需要指定
with open('a.txt','r','encoding=(gbk)') as f:这样就能读取出a.txt文件的字符串数据
当python写入文件时,默认使用的utf-8编码,在win上打开会乱码,因为win默认编码是gbk
# 打开文件
f = open("README", "w")
f.write("hello python!\n")
f.write("今天天气真好")
# 关闭文件
f.close()
按行读取文件内容
read 方法默认会把文件的 所有内容 一次性读取到内存
如果文件太大,对内存的占用会非常严重
readline 方法
readline 方法可以一次读取一行内容
方法执行后,会把 文件指针 移动到下一行,准备再次读取
读取大文件的正确姿势
# 打开文件
file = open("README")
while True:
# 读取一行内容
text = file.readline()
# 判断是否读到内容
if not text:
break
# 每读取一行的末尾已经有了一个 `\n`
print(text, end="")
# 关闭文件
file.close()
文件/目录的常用管理操作,一般使用的 os 模块
表格样式输出
test = "username\tmail\tpassword\nlibai\[email protected]\t123\nlibai\[email protected]\t123\nlibai\[email protected]\t123"
a = test.expandtabs(20)
print(a)
输出结果:
username mail password
libai [email protected] 123
libai [email protected] 123
libai [email protected] 123
将字符串中的每一个元素按 ‘+’ 号分割输出
test = "Python"
a = "+".join(test)
print(a)
输出结果:
P+y+t+h+o+n
strip 不仅仅可以去掉换行符和空格,可以是特定字符串(位于字符串首尾)
test = "Pythonon"
a = test.rstrip('on')
print(a)
输出结果:
Pyth
eval 模块转换 dict,list, tuple 格式的字符串
dict = "{'name': 'gg', 'age': 18}"
lists = "[1, 2, 3, 4, 5, 6, [7, 8]]"
tuples = "(1, 2, 3, 4, 5, 'a', 'c')"
print(eval(dict))
print(eval(lists))
print(eval(tuples))
{'name': 'gg', 'age': 18}
[1, 2, 3, 4, 5, 6, [7, 8]]
(1, 2, 3, 4, 5, 'a', 'c')
python 内置的函数中,len() 等同于 object.len()
对函数的另一种方式调用
def add(num1, num2):
return num1 + num2
def multi(num1, num2):
return num1 * num2
mute = {
1 : add,
2 : multi
}
if __name__ == "__main__":
print(mute[1](5, 6)) // 11
lambda,map, reduce, filter
lambda 是一个匿名函数表达式
gg = lambda x, y : x+y
#类似于
# add(x, y):
# return x + y
Python 的三元表达式
#条件为真时返回的结果 if 条件判断 else 条件为假时返回的结果
x = 1
y = 3
r = x if x > y else y
print(r)
map, 从 list_x 映射到一个新的 list
list_x = [1, 2, 3, 4, 5, 6, 7, 8]
def square(x):
return x * x
r = map(square, list_x)
print(r)
print(list(r))
#输出结果
#
lambda 和 map
list_x = [1, 2, 3, 4, 5, 6, 7, 8]
r = map(lambda x : x*x, list_x)
print(list(r))
lambda 和 map 传入多个参数迭代
list_x = [1, 2, 3, 4, 5, 6, 7, 8]
list_y = [1, 2, 3, 4, 5, 6, 7, 8]
r = map(lambda x, y : x*x + y, list_x, list_y)
print(list(r))
#输出结果
#[2, 6, 12, 20, 30, 42, 56, 72]
传入的 list 没有相同长度
list_x = [1, 2, 3, 4]
list_y = [1, 2, 3, 4, 5, 6, 7, 8]
r = map(lambda x, y : x*x + y, list_x, list_y)
print(list(r))
#输出结果
#[2, 6, 12, 20]
reduce
from functools import reduce
#连续计算,连续调用 lambda
list_x = ['1', '2', '3', '4', '5', '6', '7', '8']
r = reduce(lambda x,y : x+y, list_x, "aaa") # 'aaa'
print(r)
#输出结果
#aaa12345678
filter 实现一个筛选函数。依靠返回值的 True or False 来决定保留还是丢弃该元素
list_x = [1, 0, 1, 0, 1, 1, 0]
r = filter(lambda x: True if x==1 else False, list_x)
print(list(r))
#输出结果
#[1, 1, 1, 1]
函数式编程,并不适用于Python
补充一个我一直忽略的点
def showNum():
print(num)
num = 100
showNum() // 100
上面定义的函数是可以取到num的值的,python的执行顺序由上到下,先读取定义的 def showNum(),
中间的代码跳过,等到执行该函数时再回去读取执行