1. Python面向对象
2. Python正则表达式
3. Python多线程
4. Python GUI编程
5. Python JSON
类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。
类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。
数据成员:类变量或者实例变量, 用于处理类及其实例对象的相关的数据。
方法重写:如果从父类继承的方法不能满足子类的需求,可以对其进行改写,这个过程叫方法的覆盖(override),也称为方法的重写。
局部变量:定义在方法中的变量,只作用于当前实例的类。
实例变量:在类的声明中,属性是用变量来表示的。这种变量就称为实例变量,是在类声明的内部但是在类的其他成员方法之外声明的。
继承:即一个派生类(derived class)继承基类(base class)的字段和方法。继承也允许把一个派生类的对象作为一个基类对象对待。例如,有这样一个设计:一个Dog类型的对象派生自Animal类,这是模拟"是一个(is-a)"关系(例图,Dog是一个Animal)。
实例化:创建一个类的实例,类的具体对象。
方法:类中定义的函数。
对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。
使用 class 语句来创建一个新类,class 之后为类的名称并以冒号结尾,类的帮助信息可以通过ClassName.__doc__查看。class_suite 由类成员,方法,数据属性组成。这个为python类的实例:
#!/usr/bin/python
# -*- coding:UTF -*-
class Employee:
"所有员工基类"
empCount = 0
def __init__(self,name,salary):
self.name = name
self.salary = salary
Employee.empCount += 1
def displayCount(self):
print("Total Employee %d"%Employee.empCount)
def displayEmployee(self):
print("Name:",self.name,",Slary:",self.salary)
Employee.name = "Jake"
Employee.salary = 3500
Employee.empCount = 1
Employee.displayCount(Employee)
Employee.displayEmployee(Employee)
print("-----------------------------")
print(Employee)
print(Employee.name,Employee.salary,Employee.empCount)
运行结果为:
Total Employee 1
Name: Jake ,Slary: 3500
-----------------------------
<class '__main__.Employee'>
Jake 3500 1
其中,empCount 变量是一个类变量,它的值将在这个类的所有实例之间共享。你可以在内部类或外部类使用 Employee.empCount 访问。第一种方法__init__()方法是一种特殊的方法,被称为类的构造函数或初始化方法,当创建了这个类的实例时就会调用该方法self 代表类的实例,self 在定义类的方法时是必须有的,虽然在调用时不必传入相应的参数。
类的方法与普通的函数只有一个特别的区别——它们**必须有一个额外的第一个参数名称, 按照惯例它的名称是 self。**举个例子:
#!/usr/bin/python
# -*- coding:UTF -*-
class Test:
def prt(self):
print(self)
print(self.__class__)
t = Test
t.prt(t)
运行结果为:
<class '__main__.Test'>
<class 'type'>
从执行结果可以很明显的看出,self 代表的是类的实例,代表当前对象的地址,而 self.class 则指向类。self 不是 python 关键字,我们把他换成 runoob 也是可以正常执行的:。
实例化类其他编程语言中一般用关键字 new**,但是在 Python 中并没有这个关键字,类的实例化类似函数调用方式**。以下使用类的名称 Employee 来实例化,并通过 init 方法接收参数。
您可以使用点号 . 来访问对象的属性。
你可以添加,删除,修改类的属性,同时也可以用这几个函数来访问属性:
getattr(obj, name[, default]) : 访问对象的属性。
hasattr(obj,name) : 检查是否存在一个属性。
setattr(obj,name,value) : 设置一个属性。如果属性不存在,会创建一个新属性。
delattr(obj, name) : 删除属性。
对上述的描述举个例子:
#!/usr/bin/python
# -*- coding:UTF -*-
class Employee:
"所有员工基类"
empCount = 0
def __init__(self,name,salary):
self.name = name
self.salary = salary
Employee.empCount += 1
def displayCount(self):
print("Total Employee %d"%Employee.empCount)
def displayEmployee(self):
print("Name:",self.name,",Slary:",self.salary)
#实例化类,成为对象
employee1 = Employee("Peter",5000)
employee2 = Employee("Kero",4500)
employee1.displayEmployee()
employee2.displayEmployee()
print("Total Employee %d"%Employee.empCount)
print("---------------------------------------")
#对一个对象添加属性,修改属性和删除属性
employee1.age = 22
print(employee1.age)
employee1.age = 25
print(employee1.age)
del employee1.age
print(employee1.age)
print("---------------------------------------")
a = hasattr(employee2,"age") #如果存在“age属性”,则返回True
b = setattr(employee2,"age",24) #添加“age”属性和值
print(employee1.age)
c = getattr(employee2,"age") #返回"age"的值
d = delattr(employee2,"age") #删除属性
print(a,c)
print(employee1.age)
运行结果为:
Traceback (most recent call last):
Name: Peter ,Slary: 5000
File "C:/Users/10101/Desktop/Program/Python/venv/Python_Demo.py", line 34, in <module>
Name: Kero ,Slary: 4500
print(employee1.age)
Total Employee 2
AttributeError: 'Employee' object has no attribute 'age'
---------------------------------------
22
25
#!/usr/bin/python
# -*- coding:UTF -*-
class Employee:
"所有员工基类"
empCount = 0
def __init__(self,name,salary):
self.name = name
self.salary = salary
Employee.empCount += 1
def displayCount(self):
print("Total Employee %d"%Employee.empCount)
def displayEmployee(self):
print("Name:",self.name,",Slary:",self.salary)
print("Employee:__doc__:",Employee.__doc__)
print("Employee:__name__:",Employee.__name__)
print("Employee:__module__:",Employee.__module__)
print("Employee:__bases__:",Employee.__bases__)
print("Employee:__dict__:",Employee.__dict__)
运行结果为:
Employee:__name__: Employee
Employee:__module__: __main__
Employee:__bases__: (<class 'object'>,)
Employee:__dict__: {'__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'Employee' objects>, 'displayCount': <function Employee.displayCount at 0x000001836C403510>, '__dict__': <attribute '__dict__' of 'Employee' objects>, 'displayEmployee': <function Employee.displayEmployee at 0x000001836C403598>, 'empCount': 0, '__init__': <function Employee.__init__ at 0x000001836C4030D0>, '__doc__': '所有员工基类'}
Python 使用了引用计数这一简单技术来跟踪和回收垃圾。在 Python 内部记录着所有使用中的对象各有多少引用。一个内部跟踪变量,称为一个引用计数器。当对象被创建时, 就创建了一个引用计数, 当这个对象不再需要时, 也就是说, 这个对象的引用计数变为0 时, 它被垃圾回收。但是回收不是"立即"的, 由解释器在适当的时机,将垃圾对象占用的内存空间回收。
垃圾回收机制不仅针对引用计数为0的对象,同样也可以处理循环引用的情况。循环引用指的是,两个对象相互引用,但是没有其他变量引用他们。这种情况下,仅使用引用计数是不够的。Python 的垃圾收集器实际上是一个引用计数器和一个循环垃圾收集器。作为引用计数的补充, 垃圾收集器也会留心被分配的总量很大(及未通过引用计数销毁的那些)的对象。 在这种情况下, 解释器会暂停下来, 试图清理所有未引用的循环。
析构函数 __del__在对象销毁的时候被调用,当对象不再被使用时,__del__方法运行,举个例子:
#!/usr/bin/python
# -*- coding:UTF -*-
class Point:
def __init__(self,x = 0,y = 0):
self.x = 0
self.y = 0
def __del__(self):
class_name = self.__class__.__name__
print(class_name,"销毁")
pt1 = Point()
pt2 = pt1
pt3 = pt1
print(id(pt1),id(pt2),id(pt3)) #打印对象id
del pt1
del pt2
del pt3
运行结果为:
1565147697952 1565147697952 1565147697952
Point 销毁
面向对象的编程带来的主要好处之一是代码的重用,实现这种重用的方法之一是通过继承机制。通过继承创建的新类称为子类或派生类,被继承的类称为基类、父类或超类。
在python中继承中的一些特点:
1、如果在子类中需要父类的构造方法就需要显示的调用父类的构造方法,或者不重写父类的构造方法。详细说明可查看:python 子类继承父类构造函数说明。
2、在调用基类的方法时,需要加上基类的类名前缀,且需要带上 self 参数变量。区别在于类中调用普通函数时并不需要带上 self 参数。
3、Python 总是首先查找对应类型的方法,如果它不能在派生类中找到对应的方法,它才开始到基类中逐个查找。(先在本类中查找调用的方法,找不到才去基类中找)。如果在**继承元组中列了一个以上的类,那么它就被称作"多重继承" 。**举个例子:
#!/usr/bin/python
# -*- coding:UTF -*-
class Parent: #定义父类
parentAttr = 100
def __init__(self):
print("调用父类构造函数")
def parentMethod(self):
print("调用父类方法")
def setAttr(self,attr):
Parent.parentAttr = attr
def getAttr(self):
print("父类属性:",Parent.parentAttr)
class child(Parent): #定义子类
def __init__(self):
print("调用子类构造方法")
def childMethod(self):
print("调用子类方法")
c = child() #实例化子类
c.childMethod() #调用子类方法
c.parentMethod() #调用父类方法
c.setAttr(200) #再次调用父类方法 - 设置属性值
c.getAttr() #再次调用父类方法 - 获取属性值
运行结果为:
调用子类构造方法
调用子类方法
调用父类方法
父类属性: 200
你可以使用issubclass()或者isinstance()方法来检测。
issubclass() - 布尔函数判断一个类是另一个类的子类或者子孙类,语法:issubclass(sub,sup)
isinstance(obj, Class) 布尔函数如果obj是Class类的实例对象或者是一个Class子类的实例对象则返回true。
如果你的父类方法的功能不能满足你的需求,你可以在子类重写你父类的方法,举个例子:
#!/usr/bin/python
# -*- coding:UTF -*-
class Parent: #定义父类
def myMethod(self):
print("调用父类方法")
class Child(Parent): #定义子类
def myMethod(self): #方法的重写
print("调用子类方法")
c = Child() #子类实例
c.myMethod() #调用子类重写的方法
结果为:
调用子类方法
Python同样支持运算符重载,实例如下:
#!/usr/bin/python
# -*- coding:UTF -*-
class Vector:
def __init__(self, a, b):
self.a = a
self.b = b
def __str__(self):
return("Vector (%d %d)"%(self.a,self.b))
def __add__(self, other):
return Vector(self.a + other.a,self.b + other.b)
v1 = Vector(2,10)
v2 = Vector(5,-2)
print(v1,v2)
print(v1 + v2)
运行结果为:
Vector (2 10) Vector (5 -2)
Vector (7 8)
类的私有属性
__private_attrs:两个下划线开头,声明该属性为私有,不能在类的外部被使用或直接访问。在类内部的方法中使用时 self.__private_attrs。
类的方法
在类的内部,使用 def 关键字可以为类定义一个方法,与一般函数定义不同,类方法必须包含参数 self,且为第一个参数。
类的私有方法
__private_method:两个下划线开头,声明该方法为私有方法,不能在类的外部调用。在类的内部调用 self.__private_methods。
#!/usr/bin/python
# -*- coding:UTF -*-
class JustCounter:
__secretCount = 0 #私有变量
publicCount = 0 #公开变量
def count(self):
self.__secretCount += 1
self.publicCount += 1
print(self.__secretCount)
counter = JustCounter()
counter.count()
counter.count()
print(counter.publicCount)
print(counter.__secretCount) #报错,实例不能访问私有变量
运行结果为:
1
Traceback (most recent call last):
2
File "C:/Users/10101/Desktop/Program/Python/venv/Python_Demo.py", line 17, in <module>
2
print(counter.__secretCount) #报错,实例不能访问私有变量
AttributeError: 'JustCounter' object has no attribute '__secretCount'
Python不允许实例化的类访问私有数据,但你可以使用 object._className__attrName( 对象名._类名__私有属性名 )访问属性,参考以下实例:
#!/usr/bin/python
# -*- coding:UTF -*-
class Runoob:
__site = "www.runoob.com"
runoob = Runoob()
print(runoob._Runoob__site)
运行结果为:
www.runoob.com
正则表达式是一个特殊的字符序列,它能帮助你方便的检查一个字符串是否与某种模式匹配。Python 自1.5版本起增加了re 模块,它提供 Perl 风格的正则表达式模式。re 模块使 Python 语言拥有全部的正则表达式功能。compile 函数根据一个模式字符串和可选的标志参数生成一个正则表达式对象。该对象拥有一系列方法用于正则表达式匹配和替换。re 模块也提供了与这些方法功能完全一致的函数,这些函数使用一个模式字符串做为它们的第一个参数。本章节主要介绍Python中常用的正则表达式处理函数。
re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。
举个例子:
#!/usr/bin/python
# -*- coding:UTF -*-
import re
print(re.match('www',"www.baidu.com").span()) #在起始位置匹配
print(re.match("com","www.baidu.com")) #不在起始位置匹配
print("-----------------------------")
line = "Cats are smarter than dogs"
#注意:
# re.M 多行匹配,影响 ^ 和 $
# re.I 使匹配对大小写不敏感
matchObj = re.match(r'(.*)are(.*?).*',line,re.M|re.I)
if matchObj:
print("matchObj.group():",matchObj.group())
print("matchObj.group(1):", matchObj.group(1))
print("matchObj.group(2):", matchObj.group(2))
else:
print("No match")
输出结果为:
(0, 3)
None
-----------------------------
matchObj.group(): Cats are smarter than dogs
matchObj.group(1): Cats
matchObj.group(2):
re.search 扫描整个字符串并返回第一个成功的匹配。
举个例子:
#!/usr/bin/python
# -*- coding:UTF -*-
import re
print(re.search('www',"www.baidu.com").span()) #在起始位置匹配
print(re.search("com","www.baidu.com")) #不在起始位置匹配
print("-----------------------------")
line = "Cats are smarter than dogs"
#注意:
# re.M 多行匹配,影响 ^ 和 $
# re.I 使匹配对大小写不敏感
searchObj = re.search(r'(.*)are(.*?).*',line,re.M|re.I)
if searchObj:
print("searchObj.group():",searchObj.group())
print("searchObj.group(1):", searchObj.group(1))
print("searchObj.group(2):", searchObj.group(2))
else:
print("Nothing found")
**其中这里的正则表达式看链接进行理解。**下面有人做的笔记
输出结果为;
(0, 3)
<_sre.SRE_Match object; span=(10, 13), match='com'>
-----------------------------
searchObj.group(): Cats are smarter than dogs
searchObj.group(1): Cats
searchObj.group(2):
re.match只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回None;而re.search匹配整个字符串,直到找到一个匹配。举个例子:
#!/usr/bin/python
# -*- coding:UTF -*-
import re
line = "Cats are smarter than dogs"
#注意:
# re.M 多行匹配,影响 ^ 和 $
# re.I 使匹配对大小写不敏感
matchObj = re.match(r'dog',line,re.M|re.I) #字符串开始不符合正则表达式
if matchObj:
print("match --> matchObj.group():",matchObj.group())
else:
print("No match")
searchObj = re.search(r'dog',line,re.M|re.I)
if searchObj:
print("search --> searchObj.group():",searchObj.group())
else:
print("Nothing found")
运行结果为:
No match
search --> searchObj.group(): dog
Python 的 re 模块提供了re.sub用于替换字符串中的匹配项。
举个例子:
#!/usr/bin/python
# -*- coding:UTF -*-
import re
phone = "2004-959-559 #这是一个国外的号码"
#删除字符串中的PPython注释
num = re.sub('#.*$',"",phone)
print("电话号码是:",num)
#删除非数字(-)的字符串
num = re.sub('\D',"",phone)
print("电话号码是:",num)
运行结果为:
电话号码是: 2004-959-559
电话号码是: 2004959559
以下实例中将字符串中的匹配的数字乘以 2.在python3.5中代码实现不了。
compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用。
举个例子:
#!/usr/bin/python
# -*- coding:UTF -*-
import re
pattern = re.compile(r'\d+') #用于匹配正好一个数字
m = pattern.match("one12twothree34four") #从头部开始匹配
print(m)
m = pattern.match("one12twothree34four",2,10) #从e开始匹配
print(m)
m = pattern.match("one12twothree34four",3,10) #从1开始匹配
print(m)
a = m.group(0) #用于获得一个或多个分组匹配的字符串,当要获得整个匹配的子串时,可直接使用 group() 或 group(0);
b = m.start() #用于获取分组匹配的子串在整个字符串中的起始位置(子串第一个字符的索引),参数默认值为 0;
c = m.end() #用于获取分组匹配的子串在整个字符串中的结束位置(子串最后一个字符的索引+1),参数默认值为 0;
d = m.span() #返回 (start(group), end(group))
print(a,b,c,d)
print("--------------------------------")
pattern = re.compile(r'([a-z]+)([a-z]+)',re.I)
m = pattern.match("Hello World Wide Wed")
print(m)
a = m.span(0)
b = m.group(1)
c = m.span(1)
d = m.group(2)
e = m.span(2)
f = m.groups()
g = m.group(3)
h = m.end()
print(a,b,c,d,e,f,g,h)
运行结果为:
Traceback (most recent call last):
None
File "C:/Users/10101/Desktop/Program/Python/venv/Python_Demo.py", line 33, in <module>
None
g = m.group(3)
IndexError: no such group
<_sre.SRE_Match object; span=(3, 5), match='12'>
12 3 5 (3, 5)
--------------------------------
<_sre.SRE_Match object; span=(0, 5), match='Hello'>
在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果没有找到匹配的,则返回空列表。注意: match 和 search 是匹配一次 findall 匹配所有。
举个例子:
#!/usr/bin/python
# -*- coding:UTF -*-
import re
pattern = re.compile(r'\d+')
result1 = pattern.findall("runoob 123 Google 456")
result2 = pattern.findall("runoob123Google456",0,16)
print(result1)
print(result2)
运行结果为:
['123', '456']
['123', '4']
和 findall 类似,在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回。
#!/usr/bin/python
# -*- coding:UTF -*-
import re
it = re.finditer(r'\d+',"12a34b56c78d")
for match in it:
print(match.group())
运行结果为:
12
34
56
78
split 方法按照能够匹配的子串将字符串分割后返回列表,它的使用形式如下:
举个例子:
#!/usr/bin/python
# -*- coding:UTF -*-
import re
pattern1 = re.split('\W+',"runoob,runoob, runoob.") #识别字母,忽略标点,进行分割,最后都返回’‘
print(pattern1)
pattern2 = re.split('(\W+)',"runoob,runoob, runoob.") #识别字母,包括标点,进行分割,最后都返回’‘
print(pattern2)
pattern3 = re.split('(\W+)',"runoob,runoob,runoob.",1) #
print(pattern3)
pattern4 = re.split("a*","hello a world a big big world") #对于找不到匹配项的字符串而言,split不会对其分割
print(pattern4)
运行结果为:
['runoob', 'runoob', 'runoob', '']
C:\Python3.5.1\lib\re.py:203: FutureWarning: split() requires a non-empty pattern match.
['runoob', ',', 'runoob', ', ', 'runoob', '.', '']
['runoob', ',', 'runoob,runoob.']
return _compile(pattern, flags).split(string, maxsplit)
['hello ', ' world ', ' big big world']
正则表达式可以包含一些可选标志修饰符来控制匹配的模式。修饰符被指定为一个可选的标志。多个标志可以通过按位 OR(|) 它们来指定。如 re.I | re.M 被设置成 I 和 M 标志:
模式字符串使用特殊的语法来表示一个正则表达式:字母和数字表示他们自身。一个正则表达式模式中的字母和数字匹配同样的字符串。多数字母和数字前加一个反斜杠时会拥有不同的含义。标点符号只有被转义时才匹配自身,否则它们表示特殊的含义。反斜杠本身需要使用反斜杠转义。由于正则表达式通常都包含反斜杠,所以你最好使用原始字符串来表示它们。模式元素(如 r’\t’,等价于 ‘\t’)匹配相应的特殊字符。下表列出了正则表达式模式语法中的特殊元素。如果你使用模式的同时提供了可选的标志参数,某些模式元素的含义会改变。
**这里是链接:**https://www.runoob.com/python/python-reg-expressions.html#flags(里面有各个符号的解释及其一些例子)
多线程类似于同时执行多个不同程序,多线程运行有如下优点:
使用线程可以把占据长时间的程序中的任务放到后台去处理。
用户界面可以更加吸引人,这样比如用户点击了一个按钮去触发某些事件的处理,可以弹出一个进度条来显示处理的进度
程序的运行速度可能加快
在一些等待的任务实现上如用户输入、文件读写和网络收发数据等,线程就比较有用了。在这种情况下我们可以释放一些珍贵的资源如内存占用等等。
线程在执行过程中与进程还是有区别的。每个独立的进程有一个程序运行的入口、顺序执行序列和程序的出口。但是线程不能够独立执行,必须依存在应用程序中,由应用程序提供多个线程执行控制。
每个线程都有他自己的一组CPU寄存器,称为线程的上下文,该上下文反映了线程上次运行该线程的CPU寄存器的状态。
指令指针和堆栈指针寄存器是线程上下文中两个最重要的寄存器,线程总是在进程得到上下文中运行的,这些地址都用于标志拥有线程的进程地址空间中的内存。
线程可以被抢占(中断)。
在其他线程正在运行时,线程可以暂时搁置(也称为睡眠) – 这就是线程的退让。
Python中使用线程有两种方式:函数或者用类来包装线程对象。函数式:调用thread模块中的start_new_thread()函数来产生新线程:
#!/usr/bin/python
# -*- coding:UTF -*-
import _thread
import time
#为线程定义一个函数
def print_time(threadName,delay):
count = 0
while count < 5:
time.sleep(delay)
count += 1
print("%s:%s"%(threadName,time.ctime((time.time()))))
#创建两个线程
try:
_thread.start_new_thread(print_time,("Thread - 1",2,))
_thread.start_new_thread(print_time,("Thread - 2",4,))
except:
print("Error:无法启动线程")
while 1:
pass
运行结果:
Thread - 1:Tue Aug 6 15:39:07 2019
Thread - 2:Tue Aug 6 15:39:09 2019
Thread - 1:Tue Aug 6 15:39:09 2019
Thread - 1:Tue Aug 6 15:39:11 2019
Thread - 2:Tue Aug 6 15:39:13 2019
Thread - 1:Tue Aug 6 15:39:13 2019
Thread - 1:Tue Aug 6 15:39:15 2019
Thread - 2:Tue Aug 6 15:39:17 2019
Thread - 2:Tue Aug 6 15:39:21 2019
Thread - 2:Tue Aug 6 15:39:25 2019
Python3 通过两个标准库 _thread 和 threading 提供对线程的支持。_thread 提供了低级别的、原始的线程以及一个简单的锁,它相比于 threading 模块的功能还是比较有限的。threading 模块除了包含 _thread 模块中的所有方法外,还提供的其他方法:
我们可以通过直接从 threading.Thread 继承创建一个新的子类,并实例化后调用 start() 方法启动新线程,即它调用了线程的 run() 方法:
#!/usr/bin/python3
# -*- coding:UTF -*-
import threading
import time
exitFlag = 0
class myThread(threading.Thread):
def __init__(self,threadID,name,counter):
threading.Thread.__init__(self)
self.threadID = threadID
self.name = name
self.counter = counter
def run(self):
print("开始线程:" + self.name)
print_time(self.name, self.counter, 5)
print("退出线程:" + self.name)
def print_time(threadName, delay, counter):
while counter:
if exitFlag:
print("Threading End")
time.sleep(delay)
print("%s:%s"%(threadName,time.ctime(time.time())))
counter -= 1
#创建新线程
thread1 = myThread(1, "Thread - 1",1)
thread2 = myThread(2, "Thread - 2",2)
#开启新线程
thread1.start()
thread2.start()
thread2.join()
thread2.join()
print("退出主线程")
运行结果为:
开始线程:Thread - 1
开始线程:Thread - 2
Thread - 1:Tue Aug 6 16:14:52 2019
Thread - 2:Tue Aug 6 16:14:53 2019
Thread - 1:Tue Aug 6 16:14:53 2019
Thread - 1:Tue Aug 6 16:14:54 2019
Thread - 2:Tue Aug 6 16:14:55 2019
Thread - 1:Tue Aug 6 16:14:55 2019
Thread - 1:Tue Aug 6 16:14:56 2019
退出线程:Thread - 1
Thread - 2:Tue Aug 6 16:14:57 2019
Thread - 2:Tue Aug 6 16:14:59 2019
Thread - 2:Tue Aug 6 16:15:01 2019
退出线程:Thread - 2
退出主线程
如果多个线程共同对某个数据修改,则可能出现不可预料的结果,为了保证数据的正确性,需要对多个线程进行同步。使用 Thread 对象的 Lock 和 Rlock 可以实现简单的线程同步,这两个对象都有 acquire 方法和 release 方法,对于那些需要每次只允许一个线程操作的数据,可以将其操作放到 acquire 和 release 方法之间。如下:
多线程的优势在于可以同时运行多个任务(至少感觉起来是这样)。但是当线程需要共享数据时,可能存在数据不同步的问题。
考虑这样一种情况:一个列表里所有元素都是0,线程"set"从后向前把所有元素改成1,而线程"print"负责从前往后读取列表并打印。
那么,可能线程"set"开始改的时候,线程"print"便来打印列表了,输出就成了一半0一半1,这就是数据的不同步。为了避免这种情况,引入了锁的概念。
锁有两种状态——锁定和未锁定。每当一个线程比如"set"要访问共享数据时,必须先获得锁定;如果已经有别的线程比如"print"获得锁定了,那么就让线程"set"暂停,也就是同步阻塞;等到线程"print"访问完毕,释放锁以后,再让线程"set"继续。
经过这样的处理,打印列表时要么全部输出0,要么全部输出1,不会再出现一半0一半1的尴尬场面。举个例子,这里再python3.5运行不了,给出链接为:https://www.runoob.com/python3/python3-multithreading.html
Python 的 Queue 模块中提供了同步的、线程安全的队列类,包括FIFO(先入先出)队列Queue,LIFO(后入先出)队列LifoQueue,和优先级队列 PriorityQueue。这些队列都实现了锁原语,能够在多线程中直接使用,可以使用队列来实现线程间的同步。
这里再python3.5运行不了,给出链接为:https://www.runoob.com/python3/python3-multithreading.html
Python 提供了多个图形开发界面的库,几个常用 Python GUI 库如下:
Tkinter: Tkinter 模块(Tk 接口)是 Python 的标准 Tk GUI 工具包的接口 .Tk 和 Tkinter 可以在大多数的 Unix 平台下使用,同样可以应用在 Windows 和 Macintosh 系统里。Tk8.0 的后续版本可以实现本地窗口风格,并良好地运行在绝大多数平台中。
wxPython:wxPython 是一款开源软件,是 Python 语言的一套优秀的 GUI 图形库,允许 Python 程序员很方便的创建完整的、功能健全的 GUI 用户界面。
Jython:Jython 程序可以和 Java 无缝集成。除了一些标准模块,Jython 使用 Java 的模块。Jython 几乎拥有标准的Python 中不依赖于 C 语言的全部模块。比如,Jython 的用户界面将使用 Swing,AWT或者 SWT。Jython 可以被动态或静态地编译成 Java 字节码。
Tkinter 是 Python 的标准 GUI 库。Python **使用 Tkinter 可以快速的创建 GUI 应用程序。**由于 Tkinter 是内置到 python 的安装包中、只要安装好 Python 之后就能 import Tkinter 库、而且 IDLE 也是用 Tkinter 编写而成、对于简单的图形界面 Tkinter 还是能应付自如。
举个例子:
#!/usr/bin/python3
# -*- coding:UTF -*-
import tkinter
from tkinter import * #导入 Tkinter 库
root = Tk() #创建窗口对象的背景色
#创建两个列表
li = ['C','python','php','html','SQL','java']
movie = ['CSS','jQuery','Bootstrap']
listb1 = Listbox(root) #创建两个列表组件
listb2 = Listbox(root)
for item in li: #第一个小部件插入数据
listb1.insert(0,item)
for item in movie: #第二个小部件插入数据
listb2.insert(0,item)
listb1.pack() #将部件放置到主窗口中
listb2.pack()
root.mainloop() #进入消息循环
Tkinter的提供各种控件,如按钮,标签和文本框,一个GUI应用程序中使用。这些控件通常被称为控件或者部件。目前有15种Tkinter的部件。我们提出这些部件以及一个简短的介绍,在下面的表:
Tkinter控件有特定的几何状态管理方法,管理整个控件区域组织,一下是Tkinter公开的几何管理类:包、网格、位置。
本章节我们将为大家介绍如何使用 Python 语言来编码和解码 JSON 对象.JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,易于人阅读和编写。
使用 JSON 函数需要导入 json 库:import json。
举个例子:
#!/usr/bin/python3
# -*- coding:UTF -*-
import json
data = [{"a": 1,"b": 2,"c": 3,"d": 4,"e": 5}]
json = json.dumps(data)
print(json)
运行结果为;
[{"a": 1, "b": 2, "c": 3, "e": 5, "d": 4}]
json.loads 用于解码 JSON 数据。该函数返回 Python 字段的数据类型。
举个例子:
#!/usr/bin/python3
# -*- coding:UTF -*-
import json
jsonDate = '{"a": 1,"b": 2,"c": 3,"d": 4,"e": 5}'
text = json.loads(jsonDate)
print(text)
运行结果为:
{'b': 2, 'd': 4, 'e': 5, 'c': 3, 'a': 1}
以下运行不出来,链接为:https://www.runoob.com/python/python-json.html
最后为Python 100个例子和测试 ,连接分别为:
https://www.runoob.com/python/python-100-examples.html
https://www.runoob.com/quiz/python-quiz.html