Blog Logo

Python之基础篇

写于2018-11-12 17:06 阅读耗时35分钟 阅读量


python

俗话说:“工欲善其事,必先利其器”,做好一件事,准备工作是非常重要的,一门编程语言的学习,重要的当然是基础,基础就需要学习该门语言特有的语法特性

Python这门语言真的很简洁,很,简洁到实现一个功能或判断仅需一句话。 举例:

# 判断是奇数还是偶数
is_odd = lambda num:True if num % 2 == 0 else False

# 调用测试一下
is_odd(1) # False 奇数
is_odd(2) # True 偶数

# 快速创建二维数组列表
my_list = [[x,y]for x in range(1,3) for y in range(1,3)]

# 调用测试一下
print(my_list) # [[1, 1], [1, 2], [2, 1], [2, 2]]

# 获取重复列表里大于2的值
my_list = [1,1,2,2,3,3,4,4,5,6,7,7]
my_set = set(n for n in my_list if n > 2)

# 调用测试一下
print(my_set) # {3, 4, 5, 6, 7}

其实还有很多很多的例子,后续会有讲到。

我会按照下面的章节逐一讲解python:

  • 1.快速安装python及pycharm编辑器
  • 2.基本知识点及逻辑判断
  • 3.数据类型:列表、元组、字典、集合
  • 4.特性知识点:切片、拆包、可变类型和不可变类型、复制和继承、列表生成式
  • 5.各类函数及装饰器
  • 6.模块、包的导入和导出
  • 7.文件IO的操作
  • 8.面向对象、类和对象、封装、继承、多态、异常
  • 9.单例模式、迭代器和生成器
  • 10.序列化和反序列化、线程和进程、消息队列

1.快速安装python及pycharm编辑器

1.安装python最新版

# 第一步:安装Homebrew,打开终端,输入安装
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"

# 第二步:安装python3
brew install python3

# 第三步:设置默认Python为3.7版本的
# 找到bash_profile配置,没有就新建
vim /Users/YourMacUserName/.bash_profile

# 添加以下代码
alias python='python3'
alias pip='pip3'

# 更新配置
source .bash_profile

这样操作后在终端输入,pip或python命令时都是默认调用python3.7的而非Mac自带的python2.7版本。


2.安装pycharm编辑器

# 第一步:去官网下载pycharm
# 地址:http://www.jetbrains.com/pycharm/download/#section=mac
# 第二步:去百度找注册码激活,完成安装

建议下载的时候选择pycharm的专业版Professional,功能更强大。 万事俱备只欠东风,下一步当然会详细介绍python这门语言的语法和知识点,尽管枯燥,熬过去就算入门,相信自己。


2.基本知识点及逻辑判断

1.基本知识点

# 1.变量的介绍
a = 1
a = 'ww'
a = 3.14
a = True

# type(a) 查看数据类型
# 常用数据类型:int、str、float,bool、list、tuple、dict、set

# 2.变量名的命名规则
# 由字母、数字、下划线组成,不能以数字开头
# 小驼峰:
myName = 'ww'
# 大驼峰:
MyName = 'ww'
# 下划线:
my_name = 'ww' # (推荐)


# 3.公共运算符
# + 拼接列表,元祖,字符串
# * 复制列表,元祖,字符串

a = [1, 2]
b = [3, 4]
c = a + b # [1, 2, 3, 4]
d = a*2  # [1, 2, 1, 2]

# 4.关键字
# 具有特殊功能的关键字,不能作为函数名和变量名
'''
变量名:
['False', 'None', 'True', 'and', 'as', 'assert', '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']
'''

import keyword
kw = keyword.kwlist
print(kw)

# 5.注释
# 单行注释
'''
多行注释
'''

# 快捷键:command + /


# 6.数据类型的转换
# str 转 int
int(str)

# str 转 float
float(str)

# int 转 str
str(int)

int + float = float

# 7.输入和输出
# print默认会换行
print('ww')
a = 'hello'
b = 'world'
print(a, b) # hello world
print(a, b, sep=",") # hello,world

# 8.global的使用
global表示内存地址发生改变
num = 1
def show():
    global num
    num = 2
show()
print(num)

my_list = [1,2]
def show():
    my_list.append(3)
show()
print(my_list)

2.逻辑判断

# 1.条件语句的应用
score = int(input('请输入您的分数:'))

if score >= 90 and score <= 100:
    print('优秀')
elif score >= 70 and score < 90:
    print('良好')
elif score >= 60 and score < 70:
    print('及格')
else:
    print('不及格')

# 2.循环语句
# 0=False, 0非=Ture
num = 5
while num <=5:
    num += 1
    print('hello word')
    
# for循环 结合range
# range
for value in range(5):
    print(value)
    
# (1,6)
for value in range(1, 6):
    print(value)
    
# 步长2
for value in range(1, 6, 2):
    print(value)
    
# for和while可以结合else使用
num = 5
while num <=5:
    num += 1
    print('hello word')
else:
    print('循环结束')

for value in range(5):
    print(value)
else:
    print('循环结束')

# 3.continue&break
# continue:结束本次循环,进入下次循环
# break:跳出当前循环

# 4.enumerate增加下标index
# 元素遍历,要下标 enumerate
# 获取容器类型的每一个元素(遍历)
#(字符串, 列表, 元祖, 字典, 集合)

# 字符串
for i,val in enumerate('hello'):

# 列表
for i,val in enumerate(['苹果', '草莓']):

# 元祖
for i,val in enumerate((1, 5)):

# 字典
for key,val in {'name': 'ww','age': 18}.items():

# 集合
for val in {1, 3, 5}:

这节没什么需要特别说明的,按照语法去写就行。

Python语法So Easy,妈妈再也不用担心我的学习了~


3.数据类型:列表、元组、字典、集合

前面讲过python数据类型有: int、str、float,bool、list、tuple、dict、set 前面四个都是很简单的数据类型,整型、字符串、浮点型、布尔型,后面就是接下来讲到的稍复杂的数据类型。 数据类型:列表list元祖tuple字典dict集合set 首先说下它们各自如何声明的及它们的区别:

# 列表list[] 元祖tuple() 字典dict{} 集合set{}
# 列表与元祖区别:list 可修改 tuple 不可修改
# 字典与集合区别:dict 可重复 set 不可重复
my_list = [1, 5]
my_tuple = (1, 5)
my_dict = {'1':1, '5':5}
my_set = {1, 5}

1.列表list常用方法

# 声明
my_list = []
my_list = [1, 1.2, 'abc', True]

# 增末尾
my_list.append(1)

# 增任意位置
my_list.insert(1, 'abc')

# 删末尾
my_list.pop()

# 删指定数据,没有会奔溃
my_list.remove('abc')

# 删下标
del my_list[0]

# 改
my_list[-1] = '葡萄'

# 查
result = my_list[-1]

# 是否在列表
# 在列表
'西瓜' in my_list

# 找下标,没有会奔溃
my_list.index('草莓')

2.元祖tuple常用方法

能用tuple的地方就不用list,性能比list好,存储空间比list小。 不可增删改,所以只能查询。

# 声明
my_tuple = (1, 4, 'abc', True, 1.2)

# 查
my_tuple[-1]

# 注意:一个元素,类型即元素类型;多个元素,类型即元祖类型(1, )
type((1)) # <class 'int'>
type((1,)) # <class 'tuple'>

3.字典dict常用方法

# 声明
my_dict = {'name': 'ww', age: 18}

# 增
my_dict['sex'] = '男'

# 删
del my_dict['sex']

# 随机删除键值对
my_dict.popitem()

# 指定删除键值对
my_dict.pop('sex')

# 改
my_dict['sex'] = '女'

# 查 找键,没有会奔溃
my_dict['sex']

# 查 找键,不会奔溃,且默认值男
my_dict.get('sex', '男')

# 获取所有key
my_dict.keys()
# 获取所有value
my_dict.values()
# 是否在字典中
'age' in my_dict

4.集合set常用方法

# 声明
my_set = set()
my_set = {1, 4, 'abc', 'hello'}

# 增
my_set.add(5)

# 删,没有会奔溃
my_set.remove('abc')

# 删,不会奔溃
my_set.discard(1234)

5.列表list,元祖tuple,集合set,互相转换

为什么没字典dict,因为它是key-value格式的,不支持。

my_list = [1, 5]
my_tuple = (1, 5)
my_set = {1, 5}

# list转set,排除重复值
my_list = [1, 3, 3, 5]
my_set = set(my_list) # {1, 3, 5}
 
# list转tuple,变成常量,不可增删改
my_tuple = tuple(my_list) # (1, 3, 3, 5) 

4.高级知识点:切片、拆包、可变类型、不可变类型、复制、继承

1.切片

切片,简单理解就是快速获取值的一种方式,很强大。

# (列表list、元祖tuple、字典dict、集合set、字符串str)
# 获取需要的值,举例list,其他类型类似
Arr = ['Michael', 'Sarah', 'Tracy', 'Bob', 'Jack']

# 第一个
Arr[0]  # 'Michael'

# 最后一个
Arr[-1] # 'Jack'

# 跳过第三个,其余的所有
Arr[3:] # ['Bob', 'Jack']

# 获取前四个
Arr[:4] # ['Michael', 'Sarah', 'Tracy', 'Bob'] 

# 每隔一个,获取
# 参数[开始:结束:步长值]
Arr[0:5:2]
# 可简写成
Arr[::2] # ['Michael', 'Tracy', 'Jack']

2.拆包

拆包,简单理解成javascript的ES6解构。

# 把一个数据使用不同的变量保存
# (列表list、元祖tuple、字典dict、集合set、字符串str)

# 列表
num1, num2 = [1, 5]

# 元祖
num1, num2 = (1, 5)

# 字典
key1, key2 = {'name':'ww', 'age':18}.values()

# 集合
num1, num2 = {1, 5}

# 字符串
a, b, c = 'abc'

3.可变类型和不可变类型

可变类型:列表list、字典dict、集合set 赋值时,原来的堆销毁,创建新堆,内存地址改变。

不可变类型:字符串str、数字number、元祖tuple 赋值时,栈引用重新指向堆,内存地址不变。

不可变类型性能大,存储空间小。

# 引用
# 通过id访问内存地址
a = 1
b = a
id(a) # 4506634176
id(b) # 4506634176

# 列表
my_list = [1, 2, 3]
id(my_list) # 4330354760

my_list2 = [1, 2, 3]
id(my_list2) # 4330354824

# 集合
my_dict = {'name':'ww', 'age':18}
id(my_dict) # 4329891952

my_dict2 = {'name':'ww', 'age':18}
id(my_dict2) # 4330352216

# 字典
my_set = {1, 2, 'ww'}
id(my_set) # 4329889576

my_set2 = {1, 2, 'ww'}
id(my_set2) # 4330319208

# 字符串
my_str = 'hello'
id(my_str) # 4330358240

my_str2 = 'hello'
id(my_str2) # 4330358240

# 数字
my_num = 1
id(my_num) # 4297644416

my_num2 = 1
id(my_num2) # 4297644416

# 元祖
my_tuple = (1, 2, 3)
id(my_tuple) # 4329967760

my_tuple2 = (1, 2, 3)
id(my_tuple2) # 4329967760

4.复制和继承

my_list = [1, 1.2, 'abc', True]

# 复制
my_list_copy = my_list.copy()

my_list2 = [3, '草莓']
# 继承
my_list.extend(my_list2)
my_list # [1, 1.2, 'abc', True, 3, '草莓']

5.列表生成式

# 快速创建列表
my_list = [value for value in range(0,6)]

# 统计每个元素的个数
my_list = [len(value) for value in ['abc', 'ab']]

# 所有的元素乘2
my_list = [value*2 for value in range(0,6)]

# 所有字符串增加字符
my_list = [value + ',name' for value in ['abc', 'ab']]

# 双层循环
my_list = [[x,y]for x in range(1,3) for y in range(1,3)]

# 结合if语句使用
my_list = [value for value in range(1,11)if value % 2 == 0]

5.各类函数及装饰器

1.内置函数

# 可以直接使用
# print、len、max、min、sorted、del、open...

2.基本函数和变量

# 1.函数的介绍 对代码进行复用
def show():
    print('hello')
show()

# 2.函数的定义和调用
# 定义:
# def 函数名(参数):
#     功能实现

# 调用:
# 函数名()

def show(name, age):
    print('name:%s,age:%d'%(name, age))
show('ww', 18)

# 3.函数的四种类型
# 无参无返回值
def show():
    print('hello')

# 有参数无返回值
def show(name):
    print(name)

# 无参数有返回值
def show():
    return 'hello'

# 有参数有返回值
def show(name):
    return name

# 4.局部变量
# 函数内定义的变量

# 5.全局变量
# 函数外定义的变量
score = 100
def show():
    score = 99
show()
print(score) # 100

3.传参

# 1.缺省参数
# 定义时,参数就有值
# 缺省参数必须在必选参数的后面
def sum(a, b = 1):
    return a + b
sum(20) # 21

# 2.位置传参和关键字传参
def sum(a, b = 1):
    return a + b
sum(b = 2, a = 20) # 22

# 3.不定长参数
# 封装成tuple 
def sum(*args):
    count = 0
    for num in args:
        count += num
    return count
sum(1, 2, 3, 4)

# 封装成dict
def show(**kwargs):
    for key, value in kwargs.items():
        print(key, value)
show(a = 1, c = 2, b = 3, d = 4)

# 4.不定长关键字参数的使用
def show(**kwargs):
    print(kwargs)

def show_msg(**kwargs):
    show(**kwargs)
show_msg(a = 1, b = 2)

# 5.不定长位置参数的高级使用
def show(*kwargs):
    print(kwargs)

def show_msg(*kwargs):
    show(*kwargs)
show_msg(1, 2)

4.复杂的函数

# 1.复杂的函数使用
# 最常见的方式
def show(name, age, *args, **kwargs):
    print(name, age, args, kwargs)

# 2.函数的注意事项
# a.函数名相同会被覆盖掉
# b.变量名和函数名不能一样

# 3.必须使用关键字参数调用函数
def show(*, name, age):
    print(name, age)
show(name = 'ww', age = 16)

# 4.函数的嵌套
# 函数里定义一个函数
def show:
    def test()
        print('hello')
    test()
show()

5.高阶函数

# 1.递归函数
# 特性:传递+回归
# 阶乘
def calc_num(num):
    if num == 1:
        return 1
    else:
        return num * calc_num(num - 1)
calc_num(6)

# 获取递归次数,默认1000次
import sys
sys.getrecursionlimit() # 1000

sys.setrecursionlimit(1200)

# 2.匿名函数
# 简化代码 lambda关键字
(lambda x,y:x+y)(1,2)

# 乘法
func = (lambda x,y:x*y)
func(2, 3)

# 是否偶数
is_odd = lambda num:True if num % 2 == 0 else False
is_odd(1)

# 字典列表排序
my_list = [{'name':'ww', 'age':18},{'name':'zl', 'age':16}]
# 简写
my_list.sort(key=lambda item:item['age'])
# 全写
def get_value(item):
    return item['age']
my_list.sort(key=get_value)

# 3.偏函数
import functools
def show(a, b, c=1):
    return a + b + c
# 定义偏函数
show2 = functools.partial(show, b = 4)
show2(2) # 7 2+4+1

# 可以对内部函数使用偏函数
int2 = functools.partial(int, base = 2)
int2("11") # 3 十进制转二进制

# 4.返回函数
# 函数嵌套
# 返回函数是高级函数的一种

def show():
    def draw():
        print('--draw--')
    return draw
draw = show()
draw()

# 定义返回函数
def calc(operation):
    if operation == '+':
        return (lambda x,y:x+y)
    elif operation == '-':
        return(lambda x,y:x-y)
    else:
        pass

# 调用返回函数        
add = calc('+')
reduce = calc('-')
add(1, 2) # 3
reduce(1, 2) # -1

# 5.高阶函数
# 函数的参数是另一个函数,返回一个函数,就是高阶函数
def add(a, b):
    return a+b
def reduce(a, b):
    return a-b
def calc(a, b, add):
    return add(a, b)
    
calc(1, 2, add) # 3
calc(1, 2, reduce) # -1

# 6.闭包
# 闭包也是一个高阶函数
# 闭包应用场景:根据参数生成不同的返回函数
def hello(msg, count):
    def return_msg():
        result = msg * count
        return result
    return return_msg
    
new_func1 = hello('A', 2)
new_func2 = hello('B', 2)

new_func1()
new_func2()

6.装饰器

# 本质上是一个函数,可以给原函数的功能进行扩展
def show():
    print('AAA')
    
def decorator(func):
    # 定义
    def inner():
        print('---', end='  ')
        # 调用show
        func()
    return inner

# 重新给show赋值
show = decorator(show)
show() # '--- AAA'

# 1.装饰器
def decorator(func):
    # 定义
    def inner():
        print('---', end='  ')
        # 调用show
        func()
    return inner

# 重新给show赋值
# 语法糖修饰(修饰show函数,给show函数增加新的功能)
@decorator
def show():
    print('AAA')

show() # '--- AAA'

# 2.装饰器修饰带有参数的函数
def decorator(func):
    def inner(a, b):
        print('计算结果如下')
        return func(a, b)
    return inner

@decorator
def sum(a, b):
    return a + b
sum(1, 5)

# 3.通用的装饰器
装饰器可以修饰任何函数

def decorator(func):
    def inner(*args, **kwargs):
        print('计算结果如下')
        return func(*args, *kwargs)
    return inner
    
@decorator
def sum1(a, b):
    return a + b
sum1(1, 5)

@decorator
def sum2(a, b, c):
    return a + b + c
sum2(1, 5, 10)

# 4.带有参数的的装饰器
def get_decorator(char):
    def decorator(func):
        def inner():
            print(char)
            print('---', end='  ')
            func()
        return inner
    return decorator

@get_decorator('AAA')
def show():
    print('OK')

show() # 'AAA --- OK'

6.模块、包的导入和导出

# 1.模块的介绍
# 一个py文件就是一个模块
# 模块里面可以定义类,定义函数,定义全局对象,实现某些功能

# 2.内置模块
# python自带的模块
# 举例:datetime 、sys、os、time、html、random

# 循环两次
for i in range(2)

# 从99递减到0
for i in range(99, 0, -1)

# 查询一个对象
dir(obj)

# 间隔1秒执行
time.sleep(1)

# 生成1~60之间的随机数
random.randint(1, 60)

# 一个对象是否在另一个对象
for cha in 'Hello'

# 一个对象的大小
len('Hello')

# 3.自定义模块
# 定义一个全局变量
# first_module.py:
g_num = 10
def show():
    pass
class Teacher():
    pass

# 导入
import first_module
first_module.num
first_module.show()
first_module.Teacher()

# 查看当前主模块
__name__

if __name__ == '__main__':
    pass

# 4.模块的导入
# 1.直接导入
# import 导入模块名

import first_module

# 2.部分导入
# from 模块名 import 功能代码

from first_module import show

# 3.限制导入特定的功能
# first_module.py里面
__all__ = ['g_num']

# from 模块名 import *
import first_module
first_module.show() # 报错

# 4.给import模块名设置别名
import first_module as first
first.show()

from first_module import show as show_msg

# 5.模块导入的注意点
# 这种导入需要保证当前模块不要定义导入的功能代码
from first_module import show
def show():
    pass
show() # 覆盖了功能代码

import first_module
first_module.show()

# 自定义模块名不要和系统模块名重复

# 查看模块搜索的顺序
import sys
sys.path

# 6.包
# 文件夹里面有__init__.py的文件
# 包是管理模块的,模块是整理功能代码

# 7.包的导入
# 和模块导入类似

# 导入第一个模块
import first_package.first_module
from first_package import first_module

# 设置模块别名
import first_package.first_module  as first

first.show()

# 直接导入包,不会自动导入对应模块,
# 需去__init__.py里面指定导入的模块。
# first_package里面的__init__.py,设置
__all__ = ['first_module']
import  first_module

import first_package
first_module.show()

7.文件IO的操作

# 1.文件的介绍
# 文件做到永久存储,可以放硬盘,数据库,mysql,mongodb等

# 2.文件的读写
# 打开文件 open
# ------r模式(只读) 没有会报错
file = open('1.txt', 'r')
file.read()
file.close()

# ------w模式(只写) 
# 文件不存在,会创建一个打开
# 文件存在,会清空原有数据
file = open('1.txt', 'w',encoding='utf-8')
# 多次写入,不会覆盖
file.write('A')
file.write('B')
file.close()

# 查看文件格式
file.encoding
Mac,Linux('utf-8') Windows('gbk') cp936

# ------a模式(追加写入) 
# 文件存在,会追加原有数据
file = open('1.txt', 'a')
file.write('C')
file.close()

# ------rb模式(二进制方式读取) 
file = open('1.txt', 'rb')
# 中文会出现\xe4\xb8\xad,一个中文三个字节
file.read() # A\xe4\xb8\xad
# 可以解码
file.read().decode('utf-8')
file.close()


# ------wb模式(二进制方式写入) 
file = open('1.txt', 'wb')
# 包装成二进制编码
file.write('A果'.encode('utf-8'))
file.close()

# ------ab模式(二进制方式追加) 
file = open('1.txt', 'ab')
file.write('C果'.encode('utf-8'))
file.close()

# ------爬视频、图片、文本、音频,常用的rb、wb、ab
# r+ w+ a+ 支持读写
# rb+ wb+ ab+ 支持二进制读写

file = open('1.txt', 'r+')
file.write('abc')
res = file.read()
print(res)
file.close()

# 7.文件的不同读取操作
read()  # 读全部
readLine() # 读一行
readLines() # 读全部,但每行读

# 8.文件的拷贝
file = open('1.txt', 'rb')
file_data = file.read()
new_file = open('1[副本].txt', 'wb')
new_file.write(file_data)
file.close()
new_file.close()

# 9.模拟大文件的拷贝
file = open('1.txt', 'rb')
new_file = open('1[副本2].txt', 'wb')
# 一次性只读1024个字节
while True:
    file_data = file.read(1024)
    # 判断数据是否读取完毕
    # 判断file_data是否为None
    if file_data:
        new_file.write(file_data)
    else:
        print('数据读取完成', new_file)
        break
file.close()
new_file.close()

# 10.if判断的扩展
# 原来if判断:True False(非False即真)
# 容器类型(非0非None即真)
if False:
    ....
if 0:
    ....
if None:
    ....
    
# 11.文件和文件夹相关的操作
# 导入模块
import os

# 重命名文件|文件夹
os.rename('1.txt', '2.txt')
os.rename('TEST', 'TEST2')

# 创建文件夹
os.mkdir('TEST')

# 当前路径
os.getcwd()

# 切换到指定目录
os.chdir('TEST')

# 删除文件
os.remove('1.txt')

# 删除文件夹
os.rmdir('TEST')

# 12.StringIO和ByteIO
# StringIO和文件写入、读取操作类似
# 向内存写入和读取String数据、二进制数据
import io
str_io = io.StringIO()
byte_io = io.BytesIO()

byte_io.write('哈哈'.encode('utf-8'))
# 1.读取所有
data = byte_io.getvalue()
# 2.读取,需设置光标
byte_io.seek(0)
data = byte_io.read()

content = data.decode('utf-8')

8.面向对象、类和对象、封装、继承、多态、异常

1.面向对象

# 1.面向对象和面向过程
# 面向过程:提供方法(自己干)
# 面向对象:功能对象提供方法(对象干)

# 举例:
# 实现炒菜的功能
# 过程:洗菜->切菜->准备作料->进行翻炒->出彩
# 对象:厨师(洗菜->切菜->准备作料->进行翻炒->出彩)

# 2.类和对象的关系
# 类:事或物的一个分类,类只是一个概念
# 对象:具体到某一个事或物

# 举例:
# 汽车->类
# 奥迪Q7->对象

# 电瓶车->类
# 我的电瓶车->对象

2.类和对象

# 1.类的定义
# 类:属性(特征)和方法(行为)
# python3默认继承object

# 旧式类的创建方式
class Teacher():
    country = None
    def show(self):
        pass
teacher = Teacher()
teacher.show()
teacher.country

# 继承的类
Teacher.__bases__

# 2.新式类的创建方式
# 为了兼容不同的python版本,建议使用该方式创建类
class Teacher(object):
    country = None
    def show(self):
        pass

# 3.动态添加对象的属性,获取属性值
# 创建对象
teacher = Teacher()

# 动态添加的属性
teacher.name = None

# 获取属性值
teacher.country

# 调用方法
teacher.show()

3.常见魔法方法

# 含__xxx__的方法
# 1.__new__魔法方法
# 创建对象是自动调用两个方法,先__new__,再__init__
class Teacher(object):
    def __new__(cls):
        print('创建一个对象')
        return object.__new__(cls)
    def __init__(self):
        print('初始化')
        
# 2.__init__魔法方法
# 对象初始化时__init__会被调用

class Teacher(object):
    # init方法里面添加参数,self表示当前对象
    def __init__(self, country):
        self.country = country
    def show(self):
        pass
        
# 3.__del__魔法方法
# 对象释放时回自动调用
class Teacher(object):
    def __init__(self, country):
        self.country = country
    def __del__(self):
        print('对象销毁了', self)

teacher = Teacher('小明')
# 退出程序时
exit() # 对象销毁了 <__main__.Teacher object at 0x101ac5e80>

# 销毁对象
del teacher

# 4.__str__魔法方法
# 使用print对象时__str__会被调用

class Teacher(object):
    def __init__(self, country):
        self.country = country
    def __str__(self):
        return '出生地:%s'%(self.country)
    def show(self):
        pass
 
teacher = Teacher('成都')
print(teacher) # 出生地:成都

# 5.__slots__魔法方法
# 创建对象时不能再添加其他属性
class Person(object):
    # 对象固定属性
    __slots__ = ('name', 'age')
    def __init__(self, name, age):
        self.name = name
        self.age = age
    
p = Person('小明', 18)
p.sex = '男'

4.继承

# 1.单继承
# 类的三大特征:继承、封装、多态
# 继承好处:子类可以复用父类的属性和方法
class Person(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age
    def show(self):
        print(self.name, self.age)

class Student(Person):
    pass

xiao_ming = Student('小明', 18)
xiao_ming.show()
xiao_wei = Student('小伟', 16)
xiao_wei.show()

# 2.多继承
# 多个父类,方法会遵循mro法则
# 类的继承顺序决定方法的调用顺序

class A(object):
    def show(self):
        print('A类')
class B(object):
    def show(self):
        print('B类')
class C(A, B):
    pass
c = C()
c.show() 

C.mro() # [<class '__main__.C'>, <class '__main__.A'>, <class '__main__.B'>, <class 'object'>]

# 3.子类重写父类的方法
class Person(object):
    def run(self):
        print('跑起来')
class Student(Person):
    def __init__(self, name):
        self.name = name
    def run(self):
        print('%s跑起来了'% self.name)

stu = Student('小明')
stu.run()

# 4.使用类名调用父类的方法
class Animal(object):
    def show(self):
        print('动物')
        
class Dog(Animal):
    def show(self):
        # self指定类的继承链,获取Dog的下一个类Animal
        super(Dog, self).show()
        print(self.__class__.mro())
dog = Dog()
dog.show()

# 5.多继承super的使用
class A(object):
    def show(self):
        print('A类')
class B(object):
    def show(self):
        print('B类')
class C(A, B):
    def show(self):
        super(C, self).show()
        print('C类')
c = C()
c.show()  # A类 C类

# 6.重写方法里使用super
class A(object):
    def show(self):
        print('A类')
class B(object):
    def show(self):
        print('B类')
    def f():
        pass
class C(A, B):
    def show(self):
        # 方法重写
        super(A, self).show()
    
c = C()
c.show() # A类  super(C, self).show()
c.show() # B类  super(A, self).show()

# 7.私有属性和私有方法
class Person(object):
    def __init__(self, name, age):
        # 公有属性
        self.name = name
        # 私有属性
        self.__age = age
    
    # 公有方法
    def show(self):
        print(self.name, self.age)
        
    # 私有方法
    def __show(self):
        pass

class Student(Person):
    pass

person = Person('小明', 18)
person.__dict__ # 对象中的所有属性
Person.__dict__ # 对象中的所有方法

# 约定俗成(以__开头的就是私有的)
# 子类继承父类,不能直接使用父类的私有属性和方法

# 8.类属性和实例属性
class Person(object):
    # 类属性
    type = '黑人'
    def __init__(self):
        # 实例属性
        self.name = '人'

# 查看类属性和方法
Person.__dict__

# 对象可以访问类属性但是不可以修改类属性

# 9.对象方法、类方法、静态方法
# cls当前类 self当前对象

class Person(object):
    # 对象方法
    def show(self):
        pass
    # 类方法
    @classmethod
    def show_self(cls):
        pass
    # 静态方法
    @staticmethod
    def showmsg():
        pass

5.多态

# python本质上没有多态(假象)(约定俗成)
# 多态:关注的是同一个方法,但会出现不同形式

class Text(object):
    def show(self):
        print('显示文字')
        
class Image(object):
    def show(self):
        print('显示图片')

class Video(object):
    def show(self):
        print('显示视频')

# 显示数据的方法
def show_data(object):
    object.show()

image = Image()
text = Text()
video = Video()

show_data(image)
show_data(text)
show_data(video)

6.异常

# 1.异常的介绍
# python解释器去执行代码时出错
name = ''
name + 10


# 2.异常捕获
try:
    name = ''
    name + 10
except Exception as e:
    print(e)
    
try:
    pass
except Exception as e:
    pass
else:
    pass
finally:
    pass

# 3.自定义异常类
class NumberException(Exception):
    def __init__(self):
        pass
    def __str__(self):
        return '不是数字,所以异常'

# 抛异常
raise NumberException()

# 抛系统异常
raise NameError('系统异常') 

9.单例模式、迭代器和生成器

1.单例模式

# 常用设计模式
# 不管创建多少次对象,都是一个对象
class Teacher(object):
    __instance = None
    def __new__(cls):
        if cls.__instance == None:
            print('创建一个对象')
            cls.__instance = object.__new__(cls)
        return cls.__instance
    def __init__(self):
        print('初始化')

# 创建一个对象
teacher = Teacher()

# 再创建一个对象
teacher2 = Teacher()

# 内存地址都一样

2.迭代器和生成器

# 1.可迭代对象
# 使用for循环遍历取值的对象:列表,元祖,字典,集合,字符串,range

# 判断是否是可迭代对象
from collections import Iterable
isinstance([1, 2], Iterable)

isinstance(value, type)

# 可迭代对象有一个__iter__方法

# 2.迭代器
# 用的不是很多
# 作用:根据数据的位置获取下一个位置的值
占用内存少

from collections import Iterable

class MyIterable(object):
    def __init__(self):
        self.mylist = [4, 5, 9]
        self.current_index = 0
    def __iter__(self):
        return self
    def __next__(self):
        if self.current_index < len(self.mylist):
            res = self.mylist[self.current_index]
            self.current_index += 1
            return res
        else:
            raise StopIteration

# 创建迭代器
my_iterable = MyIterable()
isinstance(my_iterable, Iterable)
next(my_iterable)

# 3.生成器
# 生成器:特殊的迭代器,可以通过next函数和for取值
# 占用内存相当少

# 值只能向后取值,不能向前取值

# 使用生成器的表达式
next( [x for x in range(4)] ) # 'list' object is not an iterator
next( (x for x in range(4)) )

def show():
    for x in range(4):
        # 代码遇到yield会暂停,然后把结果返回过去
        # 下次启动生成器会暂停该位置
        # yield特点:可以返回多次值,return只能返回一次
        yield x
g = show()
next(g)

9.序列化和反序列化、线程和进程

1.序列化和反序列化

# 1.序列化
# 把内存的数据保存到本地,数据持久化
# 比较通用,可以序列化任何数据
# 任何数据,列表,对象等
import pickle
my_list = [{'name':'ww', 'age':18},{'name':'zl', 'age':16}]

# 得到二进制数据,写入二进制文件
file = open('1.serialize', 'wb')
pickle.dump(my_list, file)
file.close()

# 2.反序列化
import pickle
file = open('1.serialize', 'rb')
my_list = pickle.load(file)
file.close()

# 3.json序列化
import json
my_list = [{'name':'ww', 'age':18},{'name':'zl', 'age':16}]

file = open('mylist.json', 'w', encoding='utf-8')
# 序列化
json.dump(my_list, file)

file = open('mylist.json', 'r', encoding='utf-8')
# 反序列化
my_list = json.load(file)

file.close()

# 自定义类型
class Student(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

file = open('student.json', 'w', encoding='utf-8')
stu = Student('ww', 18)
# 序列化对象的属性值
json.dump(stu.__dict__, file)
file.close()

2.线程和进程

# 1.线程
# 线程:执行代码的分支,默认只有一个线程
# python本质上没有线程(假象)
import threading

def A(count):
    for i in range(count):
        print('A')
def B(count):
    for i in range(count):
        print('B')

# 创建子线程
# target:表示目标函数 args:元祖的方式给函数传参
one = threading.Thread(target = A, args = (10, ) )
two = threading.Thread(target = B, kwargs = {'count': 10} )
one.start()
two.start()

# 2.主线程会等待所有子线程执行完毕之后再退出
# 线程相关设置,都要放在线程启动之前
one.setDaemon(True) //设置守护线程
one.start()

# 3.互斥锁
lock = threading.Lock()
# 上锁
lock.acquire()

# 释放锁
lock.release()

# 4.进程
# 进程:每次创建一个进程操作系统会给这个进程分配对应的资源
# 一个进程里默认有一个主线程
# 真正干活的是线程,进程只通过资源
# 多进程可以完成多任务
import multiprocessing

def A(count):
    for i in range(count):
        print('A')
def B(count):
    for i in range(count):
        print('B')

# 创建子进程
# target:表示目标函数 args:元祖的方式给函数传参
one = multiprocessing.Process(target = A, args = (10, ) )
two = multiprocessing.Process(target = B, kwargs = {'count': 10} )
one.start()
two.start()

# 5.主进程会等到子进程执行完毕之后退出
one.daemon = True //设置守护线程
one.start()

# 6.进程之间不共享全局变量
one.join()

3.消息队列

import multiprocessing
# 创建消息队列
queue = multiprocessing.Queue(3)
# 消息队列里面添加数据
queue.put(1)
queue.put(2)
queue.put(3)
# 获取队列值
queue.get()

# 进程之间可以使用消息队列通信
# 多任务使用线程和进程
# 从资源的角度来说,进程更加节省资源
# 进程消耗的资源比较多

# 从代码稳定性来说:多进程要比多线程稳定性要强
# 因为一个进程挂掉,不会影响其他应用程序

此致,python的基础篇就全部结束了,知识点确实有点多,但不求每个都记住,但前八章的知识点和概念必须掌握,因为后续的python开发中几乎都能有所涉及。每周进步一点点!

Headshot of Maxi Ferreira

怀着敬畏之心,做好每一件事。