Python3 基础+提升

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))

#输出结果
#
#[1, 4, 9, 16, 25, 36, 49, 64]

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(),
中间的代码跳过,等到执行该函数时再回去读取执行

你可能感兴趣的:(Python3 基础+提升)