Python高级编程
python中一切皆对象
—python中一切皆对象
内容
# 变量,函数,类,文件都是对象
[对象的三个特征]
1.身份
2.类型
3.值
[对象的性质]
1.赋值给一个变量
2.可添加到内置类型中
3.可作为参数传递
4.可作为函数的返回值
对象的三个特征
'''
以变量作为例子
'''
a = 1
print(id(a)) # 身份
print(type(a)) # 类型
print(a) # 值
[输出]:
>>140706136249376
>><class 'int'>
>>1
对象的性质
'''
以类作为例子
'''
class Myclass:
def say(self):
print('hello')
# 1.类实例赋值给变量
myclass=Myclass()
a = list()
b = set()
c = dict()
d = set()
# 2.类实例放入内置数据类型
a.append(myclass) # 将类实例放入列表
b = (myclass,) # 将列实例放入元组
c.update({'class':myclass}) # 将类实例放入字典
d.add(myclass) # 将类实例放入集合
# 3.调用类实例中的方法
a[0].say() # 调用Myclass类中say()方法
b[0].say() # 调用Myclass类中say()方法
c['class'].say() # 调用Myclass类中say()方法
d.pop().say() # 调用Myclass类中say()方法
# 4.类实例作为参数传递和作为函数返回值
def myfunc(class_instance):
return class_instance # 将类实例作为函数返回值
myfunc(myclass).say() # 调用Myclass类中say()方法
[输出]:
>>hello
>>hello
>>hello
>>hello
>>hello
—type,object和class的关系
图解
说明
type 实例化生成所有类包括自身
object 被所有类和对象继承,但自身继承为空
type ->type
type ->int
type ->float
type ->complex
type ->bool
type ->dict
type ->set
type ->str
type ->list
type ->tuple
type ->bytes,bytearray
以上这些内置类型都可以看作是type实例化得到的对象
这些生成的对象又可以作为类实例化出对象,最后值不能再实例化
—python中的常见内置类型
None(全局只生成一个)
数值(int,float,complex,bool)
序列类型(str,list,tuple,range,bytes,bytearray,memoryview)
散列类型(dict,set)
迭代类型
上下文管理
其他
魔法方法
—字符串相关
方法名
__str__ __repr__
实例
class Myclass:
def __init__(self,user_print,developer_print):
self.user_print = user_print
self.developer_print = developer_print
def __str__(self):
return self.user_print
def __repr__(self):
return self.developer_print
myclass = Myclass("面向用户的打印模式","面向开发的打印模式")
print(str(myclass))
print(repr(myclass))
[输出]:
>>面向用户的打印模式
>>面向开发的打印模式
多线程
创建线程
1.使用Thread方法创建线程
import threading # 引入threading多线程模块
def task(c1):
print("传入的参数:",c1)
print(threading.current_thread()) # 获取当前的线程名和线程ID
t = threading.Thread(target=task,args=(100,),name='子线程')
# target 参数传入函数名
# args 参数传入函数需要的参数
# name 参数传入自定义的线程名
t.start() # 启动线程
t.join() # 线程阻塞
print("主线程")
[输出]:
>>传入的参数: 100
>><Thread(子线程, started 13508)>
>>主线程
2.类的方式创建线程
import threading
class Mythread(threading.Thread):
def __init__(self,name,c1):
super().__init__() # 重写Thread类中的init方法
self.name = name # name参数传入自定义的线程名
self.c1 = c1 # c1为传入的自定义参数
def run(self):
print("传入的参数:",self.c1)
print(threading.current_thread()) # 获取当前的线程名和线程ID
t = Mythread(name='子线程',c1=100) # 传入线程名和自定义参数
t.start() # 启动线程
t.join() # 线程阻塞
print("主线程")
[输出]:
>>传入的参数: 100
>><Mythread(子线程, started 10736)>
>>主线程
多线程常用方法和属性
Thread 类
实例化线程
对象=threading.Thread(name=自定义线程名,target=函数名,args=(参数,))
设置线程名
对象.setName(‘线程名’)
获取线程名
对象.getName()
线程守护(主线程结束它的子线程就结束)
对象.setDaemon(True)
线程阻塞(主线程等子线程结束后才接着往下走)
对象.join()
判断线程是否存活
对象.is_alive()
通过对象获取线程ID
对象.ident
开启线程
对象.start()
获取所有线程详细信息列表
threading.enumerate()
在线程执行过程中获取所在线程名
threading.current_thread().name
在线程执行过程中中获取所在线程ID
threading.current_thread().ident
在函数执行过程中获取线程存活数量
threading.active_count()
1.守护线程
import threading
import time
def task():
time.sleep(5)
print("子线程")
t = threading.Thread(target=task) # 传入要执行的函数名
t.setDaemon(True) # True :将线程设为守护线程 False :不将线程设为守护线程
t.start() # 启动线程
print("主线程")
[t.setDaemon(True)时输出]:
主线程
[t.setDaemon(False)时输出]:
主线程
子线程
- 将线程设置为
守护线程
模式,主线程结束
,子线程也会立即结束
- 若线程
不是守护线程模式
,主线程结束后
,还要所有子线程结束
之后,整个程序才会结束
2.线程阻塞
import threading
import time
def task():
time.sleep(5)
print("子线程")
t = threading.Thread(target=task) # 传入要执行的函数名
t.start() # 启动线程
t.join() # 线程阻塞
print("主线程")
[有t.join()语句时输出]:
子线程
主线程
[没有t.join()语句时输出]:
主线程
子线程
- 将线程设置为
线程阻塞
模式,主线程要等子线程结束后才会结束
,即子线程一定在主线程之前结束 - 若线程
不是线程阻塞模式
,主线程结束后
,还要等所有子线程结束
之后,整个程序才会结束
线程同步
1.全局解释器锁GIL
import threading
sum = 0
def income():
global sum
for i in range(1000000):
sum += 1
def consume():
global sum
for i in range(1000000):
sum -= 1
# 定义线程
t_income = threading.Thread(target=income)
t_consume = threading.Thread(target=consume)
# 启动线程
t_income.start()
t_consume.start()
# 线程阻塞
t_income.join()
t_consume.join()
# 打印变量计算结果
print("sum:",sum)
[输出]:
sum: 566204
- GIL锁即python自带的
全局解释锁
,每次只能一个线程获得cpu的使用权
,为了线程安全,也就是为了解决多线程之间的数据完整性和状态同步而加的锁,因为我们知道线程之间的数据
是共享的
。 - 由于python的全局GIL锁机制,只要一个线程执行的
字节码
或执行时间
到指定值,则会自动释放GIL锁
,此时多个线程可能同时对同一个变量同时操作,从而导致数据结果错误 - 运行结果本
应该输出sum: 0
,实际输出sum: 566204
,是因为多个线程同时对同一个变量进行修改时,一个线程得到的计算值后,可能被另一个线程的计算的值给赋值
2.互斥锁 Lock
import threading
lock = threading.Lock()
sum = 0
def income():
lock.acquire() # 加锁
global sum
for i in range(1000000):
sum += 1
lock.release() # 释放锁
def consume():
lock.acquire() # 加锁
global sum
for i in range(1000000):
sum -= 1
lock.release() # 释放锁
# 定义线程
t_income = threading.Thread(target=income)
t_consume = threading.Thread(target=consume)
# 启动线程
t_income.start()
t_consume.start()
# 线程阻塞
t_income.join()
t_consume.join()
# 打印变量计算结果
print("sum:",sum)
[输出]:
sum: 0
- 使用
lock.acquire()
,lock.release()
手动加锁保护变量
后,使每次只有一个线程获得cpu的使用权,即在同一时间,只有一个线程对变量进行修改
,所以数据并没有发生错误
3.递归锁 RLock
4.状态锁 Condition
#-*-coding:utf-8-*-
# condition实现的线程同步
import random
import threading
import time
con = threading.Condition()
apple = 0
class Producer(threading.Thread):
def __init__(self,name):
threading.Thread.__init__(self, name=name)
def run(self):
global apple
time.sleep(random.randrange(5))
with con:
print('Producer:',end='')
for i in range(1,11):
apple += 1
time.sleep(0.5)
print(f'\rProducer:生产中 剩余苹果:{apple}个',end='')
con.notify_all()
class Consumer(threading.Thread):
def __init__(self,name):
threading.Thread.__init__(self, name=name)
def run(self):
global apple
is_consumed = False
time.sleep(random.randrange(5))
with con:
if apple == 0 and is_consumed == False:
print('Consumer:等待苹果生产中...')
con.wait()
for i in range(1,11):
apple -= 1
time.sleep(0.5)
print(f'\rConsumer:消费中 剩余苹果:{apple}个',end='')
p = Producer('Produce')
c = Consumer('Consume')
p.start()
c.start()
#-*-coding:utf-8-*-
# queue实现的线程同步
import threading
import time
from queue import Queue
q = Queue()
class Producer(threading.Thread):
def __init__(self,name):
super().__init__(name=name)
def run(self):
for i in range(10):
q.put(i)
print(f'{self.name} put {i}')
time.sleep(0.2)
class Consumer(threading.Thread):
def __init__(self,name):
super().__init__(name=name)
def run(self):
for i in range(10):
print(f'{self.name} get {q.get()}')
time.sleep(0.2)
p = Producer('Producer:')
c = Consumer('Consumer:')
p.start()
c.start()
线程通信
线程池
总结
同一时间,同一个CPU中的多线程运行 --> 并发
同一时间,多个CPU中的多线程运行 --> 并行
'''常用数据类型特殊情况下的值'''
string1 = '' # 0
string2 = ' ' # 1
list1 = [] # 0
list2 = [[]] # 1
tuple1 = () # 0
tuple2 = (()) # 0
set1 = set() # 0
dict1 = {} # 0
null = None # 0
if string1:
print('string1')
if string2:
print('string2')
if list1:
print('list1')
if list2:
print('list2')
if tuple1:
print('tuple1')
if tuple2:
print('tuple2')
if set1:
print('set1')
if dict1:
print('dict1')
if null:
print('None')
[输出]:
string2
list2