一、常用模块
1、random 模块
import random print(random.random()) # 大于0小于1之间的小数 #0.9721739019776539 print(random.randint(1,3)) #大于等于1小于等于3的整数 #3 print(random.randrange(1,3)) #大于等于1小于3的整数 #2 print(random.choice([1,'alex','xglv'])) #1或alex或sb #1 print(random.sample([1,'alex','xglv'],2)) #列表中任意2个的组合 #['xglv', 'alex'] print(random.uniform(1,4)) #大于1小于4之间的小数 #2.518598386302101 l=[1,3,4,2,5] random.shuffle(l) #重新为列表排序 (洗牌) print(l) #[4, 2, 3, 1, 5] def make_code(n): res='' for i in range(n): s1=str(random.randint(0,9)) s2=chr(random.randint(65,90)) res+=random.choice([s1,s2]) return res print(make_code(7)) #HX989L8
2、os模块
方法
os.getcwd() 获取当前工作目录,即当前python脚本工作的目录路径 os.chdir("dirname") 改变当前脚本工作目录;相当于shell下cd os.curdir 返回当前目录: ('.') os.pardir 获取当前目录的父目录字符串名:('..') os.makedirs('dirname1/dirname2') 可生成多层递归目录 os.removedirs('dirname1') 若目录为空,则删除,并递归到上一级目录,如若也为空,则删除,依此类推 os.mkdir('dirname') 生成单级目录;相当于shell中mkdir dirname os.rmdir('dirname') 删除单级空目录,若目录不为空则无法删除,报错;相当于shell中rmdir dirname os.listdir('dirname') 列出指定目录下的所有文件和子目录,包括隐藏文件,并以列表方式打印 os.remove() 删除一个文件 os.rename("oldname","newname") 重命名文件/目录 os.stat('path/filename') 获取文件/目录信息 os.sep 输出操作系统特定的路径分隔符,win下为"\\",Linux下为"/" os.linesep 输出当前平台使用的行终止符,win下为"\r\n",Linux下为"\n" os.pathsep 输出用于分割文件路径的字符串 win下为;,Linux下为: os.name 输出字符串指示当前使用平台。win->'nt'; Linux->'posix' os.system("bash command") 运行shell命令,直接显示 os.environ 获取系统环境变量 os.path.abspath(path) 返回path规范化的绝对路径 os.path.split(path) 将path分割成目录和文件名二元组返回 os.path.dirname(path) 返回path的目录。其实就是os.path.split(path)的第一个元素 os.path.basename(path) 返回path最后的文件名。如何path以/或\结尾,那么就会返回空值。即os.path.split(path)的第二个元素 os.path.exists(path) 如果path存在,返回True;如果path不存在,返回False os.path.isabs(path) 如果path是绝对路径,返回True os.path.isfile(path) 如果path是一个存在的文件,返回True。否则返回False os.path.isdir(path) 如果path是一个存在的目录,则返回True。否则返回False os.path.join(path1[, path2[, ...]]) 将多个路径组合后返回,第一个绝对路径之前的参数将被忽略 os.path.getatime(path) 返回path所指向的文件或者目录的最后存取时间 os.path.getmtime(path) 返回path所指向的文件或者目录的最后修改时间 os.path.getsize(path) 返回path的大小
实践
import os print(os.stat(r"/Users/lvxingguo/PycharmProjects/oldboy/day6/代码/day6/01 常用模块/a.xml"))#获取文件的信息,可接方法查看具体信息 #os.stat_result(st_mode=33279, st_ino=32539163, st_dev=16777220, st_nlink=1, st_uid=501, st_gid=20, st_size=826, st_atime=1515922529, st_mtime=1515819080, st_ctime=1515840538) print(os.stat(r'/Users/lvxingguo/PycharmProjects/oldboy/day6/代码/day6/01 常用模块/a.xml').st_size) #826 print(os.path.getsize(r'/Users/lvxingguo/PycharmProjects/oldboy/day6/代码/day6/01 常用模块/a.xml')) #获取文件的大小 #826 res=os.system('pwd') #执行系统命令 放回结果为执行是否成功值 0成功 #/Users/lvxingguo/PycharmProjects/oldboy/day6/代码/day6/01 常用模块 print('====>',res) print(os.path.split(r'F:/Users/lvxingguo/PycharmProjects/oldboy/day6/代码/day6/01 常用模块/a.xml')) #('F:/Users/lvxingguo/PycharmProjects/oldboy/day6/代码/day6/01 常用模块', 'a.xml') print(os.path.dirname(r'/Users/lvxingguo/PycharmProjects/oldboy/day6/代码/day6/01 常用模块/a.xml')) #获取文件的目录名 #/Users/lvxingguo/PycharmProjects/oldboy/day6/代码/day6/01 常用模块 print(os.path.basename(r'/Users/lvxingguo/PycharmProjects/oldboy/day6/代码/day6/01 常用模块/a.xml')) #获取文件名 #a.xml print(os.path.isabs(r'/Users/lvxingguo/PycharmProjects/oldboy/day6')) #路径是否存在 #True print(os.path.isabs(r'/Users/lvxingguo/PycharmProjects/oldboy/day6')) #路径是否是一个绝对路径 (不判断文件是否存在) #True print(os.path.join('/Users/lvxingguo/PycharmProjects/oldboy/',"day6","lxg.txt")) #/Users/lvxingguo/PycharmProjects/oldboy/day6/lxg.txt # print(os.path.join('D:\\','dir1','dir2','a.txt')) # print(os.path.normcase('c:/windows\\SYstem32\\..')) #在win下规范路径 不处理.. # print(os.path.normpath('c://windows\\System32\\../Temp/')) #C:\windows\temp #在Win下规范目录和解析.. 切到最终的路径 linux会直接返回 print(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) #/Users/lvxingguo/PycharmProjects/oldboy/day6/代码/day6 BASE_DIR=os.path.normpath(os.path.join(os.path.abspath(__file__), '..', '..' )) #用join来拼接路径然后返回执行返回最终路径 print(BASE_DIR) #/Users/lvxingguo/PycharmProjects/oldboy/day6/代码/day6
3、sys模块
方法
1 sys.argv 命令行参数List,第一个元素是程序本身路径 2 sys.exit(n) 退出程序,正常退出时exit(0) 3 sys.version 获取Python解释程序的版本信息 4 sys.maxint 最大的Int值 5 sys.path 返回模块的搜索路径,初始化时使用PYTHONPATH环境变量的值 6 sys.platform 返回操作系统平台名称
实践
import sys # sys.argv # sys.exit(0) # sys.path print('[%-50s]' %('#'*1)) #-50 左对齐 不够用空格补齐 #[# ] print('[%-50s]' %('#'*2)) #[## ] print('[%-50s]' %('#'*3)) #[#### ] print('[%-50s]' %('#'*4)) #[##### ] print('[%-50s]' %('#'*5)) #[###### ] print("[%s]" %("#"*10).ljust(50)) #[########## ] print('[%%-%ds]' %50) #%% 转译% 来打印% #'[%-50s]' print(('[%%-%ds]' %50) %('#'*10)) #'[%-50s]' %('#'*10) #[########## ] # print(('[%%-%ds]' %50) %('#'*10)) #'[%-50s]' %('#'*10) # print(('[%%-%ds]' %50) %('#'*10)) #'[%-50s]' %('#'*10) # print(('[%%-%ds]' %50) %('#'*10)) #'[%-50s]' %('#'*10) print('%d%%' %30) #30% import time def progress(percent,width=50): #利用print if percent >= 1: percent=1 show_str = ('[%%-%ds]' % width) % ('#' * int(width*percent)) print('\r%s %d%%' %(show_str,int(100*percent)),end='') def progress_ljust(percent,width=110): #利用str的ljust方法 if percent >=1: percent = 1 print("\r[%s] %d%%"%(("="*int(width*percent)+">>").ljust(width),percent*100),end="") recv_size=0 total_size=102411 while recv_size < total_size: time.sleep(0.1) recv_size+=1024 #progress(recv_size/total_size) progress_ljust(recv_size/total_size)
4、shutil模块
http://www.cnblogs.com/linhaifeng/articles/6384466.html#_label5
5、json和pickle
之前我们学习过用eval内置方法可以将一个字符串转成python对象,不过,eval方法是有局限性的,对于普通的数据类型,json.loads和eval都能用,但遇到特殊类型的时候,eval就不管用了,所以eval的重点还是通常用来执行一个字符串表达式,并返回表达式的值。
1 import json 2 x="[null,true,false,1]" 3 print(eval(x)) #报错,无法解析null类型,而json就可以 4 print(json.loads(x))
什么是序列化?
我们把对象(变量)从内存中变成可存储或传输的过程称之为序列化,在Python中叫pickling,在其他语言中也被称之为serialization,marshalling,flattening等等,都是一个意思。
为什么要序列化?
1:持久保存状态
需知一个软件/程序的执行就在处理一系列状态的变化,在编程语言中,'状态'会以各种各样有结构的数据类型(也可简单的理解为变量)的形式被保存在内存中。
内存是无法永久保存数据的,当程序运行了一段时间,我们断电或者重启程序,内存中关于这个程序的之前一段时间的数据(有结构)都被清空了。
在断电或重启程序之前将程序当前内存中所有的数据都保存下来(保存到文件中),以便于下次程序执行能够从文件中载入之前的数据,然后继续执行,这就是序列化。
具体的来说,你玩使命召唤闯到了第13关,你保存游戏状态,关机走人,下次再玩,还能从上次的位置开始继续闯关。或如,虚拟机状态的挂起等。
2:跨平台数据交互
序列化之后,不仅可以把序列化后的内容写入磁盘,还可以通过网络传输到别的机器上,如果收发的双方约定好实用一种序列化的格式,那么便打破了平台/语言差异化带来的限制,实现了跨平台数据交互。
反过来,把变量内容从序列化的对象重新读到内存里称之为反序列化,即unpickling。
如何序列化之json和pickle:
json
如果我们要在不同的编程语言之间传递对象,就必须把对象序列化为标准格式,比如XML,但更好的方法是序列化为JSON,因为JSON表示出来就是一个字符串,可以被所有语言读取,也可以方便地存储到磁盘或者通过网络传输。JSON不仅是标准格式,并且比XML更快,而且可以直接在Web页面中读取,非常方便。
JSON表示的对象就是标准的JavaScript语言的对象,JSON和Python内置的数据类型对应如下:
实践
#json 序列化 import json dic={'a':1} x=None res1=json.dumps(dic) #str(dic) res2=str(dic) print(res1,type(res1)) #json转换后还是字符串类型 #{"a": 1} <class 'str'> print(res2,type(res2)) #{'a': 1} <class 'str'> res=json.dumps(x) print(res,type(res)) #null <class 'str'> # json序列化 import json,time user={'name':'egon','age':18,'nb':True} #json.dumps with open('user.json','w',encoding='utf-8') as f: f.write(json.dumps(user)) #user.json #{"name": "egon", "age": 18, "nb": true} students=['alex','egon','wxx','yxx'] #json.dump json.dump(students,open('students.json','w',encoding='utf-8')) #students.json #["alex", "egon", "wxx", "yxx"] # time.sleep(500) # pickle序列化 可以序列化所以python的类型 import pickle,json s={1,2,3} print(json.dumps(s)) #TypeError: Object of type 'set' is not JSON serializable json不支持python独有的数据结构 print(pickle.dumps(s)) #b'\x80\x03cbuiltins\nset\nq\x00]q\x01(K\x01K\x02K\x03e\x85q\x02Rq\x03.' 是一个byte类型 with open('s.pkl','wb') as f: f.write(pickle.dumps(s)) pickle.dump(s,open('s.pkl','wb')) #json反序列化 import json with open('user.json','r',encoding='utf-8') as f: user=json.loads(f.read()) #json.dumps print(user['name']) #egon user=json.load(open('user.json','r',encoding='utf-8')) print(user['age']) #18 print(user['nb']) #True json_str='{"count":1}' #只要是json格式的字符串就可以用json.loads来进行反序列化 #注意json格式不识别单引号、 print(json.loads(json_str)['count']) #1 # json_str="{'count':1}" # print(json.loads(json_str)) # print(json.load(open('user.json','r',encoding='utf-8'))) #pickle反序列化 import pickle with open('s.pkl','rb') as f: s=pickle.loads(f.read()) print(s,type(s)) #{1, 2, 3} <class 'set'> s=pickle.load(open('s.pkl','rb')) print(s, type(s)) #{1, 2, 3} <class 'set'>
6、shelve 模块
shelve模块比pickle模块简单,只有一个open函数,返回类似字典的对象,可读可写;key必须为字符串,而值可以是python所支持的数据类型
import shelve f=shelve.open('db.shl') f['stu1']={'name':'alex1','age':38} f['stu2']={'name':'alex2','age':28} f.close() f = shelve.open("db.shl") print(f["stu1"],type(f["stu1"])) #{'name': 'alex1', 'age': 38} <class 'dict'> print(f["stu2"],type(f["stu2"])) #{'name': 'alex2', 'age': 28} <class 'dict'> f.close()
7、xml模块
示例文件
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
<data v="1.0"> <country name="Liechtenstein"> <rank updated="yes">2</rank> <year updated="yes">2010</year> <gdppc>141100</gdppc> <neighbor direction="E" name="Austria" /> <neighbor direction="W" name="Switzerland" /> </country> <country name="Singapore"> <rank updated="yes">5 <egon age="18" name="egon">egon is good</egon> </rank> <year updated="yes">2013</year> <gdppc>59900</gdppc> <neighbor direction="N" name="Malaysia" /> </country> <country name="Panama"> <rank updated="yes">69</rank> <year updated="yes">2013</year> <gdppc>13600</gdppc> <neighbor direction="W" name="Costa Rica" /> <neighbor direction="E" name="Colombia" /> </country> </data>
实践
from xml.etree import ElementTree tree=ElementTree.parse('a.xml') root=tree.getroot() print(root) #<Element 'data' at 0x1020b38b8> print(root.tag) # 标签的名字 #data print(root.attrib) #标签的属性 #{'v': '1.0'} print(root.text) #标签的内容 # #三种查找方式 #从子节点中找 只找一层 print(root.find('country')) #只找一个 #<Element 'country' at 0x1005b39f8> print(root.findall('country')) #找到所有符合的 #[<Element 'country' at 0x1005b39f8>, <Element 'country' at 0x101ab1188>, <Element 'country' at 0x101ab1368>] print(root.find('rank')) #没有返回None #None #从整个树形结构中查找 找所有层 print(list(root.iter('rank'))) #[<Element 'rank' at 0x102a4e408>, <Element 'rank' at 0x102a961d8>, <Element 'rank' at 0x102a963b8>] print(list(root.iter('rank'))[0].tag) #rank for country in root.findall('country'): rank=country.find('rank') print(rank.tag,rank.attrib,rank.text) #rank {'updated': 'yes'} 2 #rank {'updated': 'yes'} 5 #rank {'updated': 'yes'} 69 #遍历文档树 for country in root: print('=============>',country.attrib['name']) for item in country: print(item.tag,item.attrib,item.text) # =============> Liechtenstein # rank {'updated': 'yes'} 2 # year {'updated': 'yes'} 2009 # gdppc {} 141100 # neighbor {'direction': 'E', 'name': 'Austria'} None # neighbor {'direction': 'W', 'name': 'Switzerland'} None # =============> Singapore # rank {'updated': 'yes'} 5 # year {'updated': 'yes'} 2012 # gdppc {} 59900 # neighbor {'direction': 'N', 'name': 'Malaysia'} None #....... for year in root.iter('year'): print(year.tag,year.attrib,year.text) # year {'updated': 'yes'} 2009 # year {'updated': 'yes'} 2012 # year {'updated': 'yes'} 2012 #修改 for year in root.iter('year'): year.set('updated',"yes") #添加属性 year.text=str(int(year.text)+1) #写入必须是str类型 tree.write('a.xml') #把修改写入文件 也可写入写文件 tree.write('b.xml') #添加一个节点 for country in root: obj=ElementTree.Element('egon') #<egon name="egon" age="18">egon is good</egon> #添加节点的标签名 obj.attrib={'name':'egon','age':'18'} #添加节点的属性 也可用set # obj.set("name","egon") # obj.set("age","18") obj.text='egon is good' #添加节点的内容 country.append(obj) #把新建的节点加入 country的标签里 tree.write('a.xml') #把更改写入文件 #指定写入的标签 for rank in root.iter('rank'): if int(rank.text) == 5: obj=ElementTree.Element('egon') #<egon name="egon" age="18">egon is good</egon> obj.attrib={'name':'egon','age':'18'} obj.text='egon is good' rank.append(obj) tree.write('a.xml')
8、configerparser模块
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
[mysqld] charater-server-set = utf8 default-engine = innodb skip-grant-table = True port = 3306 data_dir='C:\a\b\data' [client] user = root password = alex3714 [egon] name = egon age = 18
示例
import configparser config=configparser.ConfigParser() config.read('my.ini') print(config.sections()) #查看所有标题 #['mysqld', 'client', 'egon'] print(config.options('mysqld')) #查看某个标题下的所有选项 #['charater-server-set', 'default-engine', 'skip-grant-table', 'port', 'data_dir'] print(config.get('mysqld','charater-server-set')) #查看选项的值 #utf8 print(config.has_option('mysqld','aaa')) #查看配置是否存在 #False if config.has_option('mysqld','aaa'): print(config.get('mysqld','aaa')) print(config.getboolean('mysqld','skip-grant-table')) #得到选项的布尔值 #True print(config.getint('mysqld','port')) #得到选项的整型 #3306 print(config.getfloat('mysqld','port')) #得到选项的浮点型 #3306.0 config.add_section('egon') #添加一个标题 若存在报错 #configparser.DuplicateSectionError: Section 'egon' already exists config.set('egon','name','egon') #添加一个选项 config.set('egon','age','18') config.set('client','password','alex3714') #更改 config.write(open('my.ini','w',encoding='utf-8')) #把更改写入文件
9、hashlib模块
hash:一种算法 ,3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224, SHA256, SHA384, SHA512 ,MD5 算法
三个特点:
1.内容相同则hash运算结果相同,内容稍微改变则hash值则变
2.不可逆推
3.相同算法:无论校验多长的数据,得到的哈希值长度固定。
import hashlib #哈希的两种用途,1、加密(加密密码) 2、校验(如下载文件后和服务端的校验) m=hashlib.md5() #使用哈希中的md5算符 m.update('hello'.encode('utf-8')) #只接受bytes格式 否则报错 TypeError: Unicode-objects must be encoded before hashing m.update('world'.encode('utf-8')) # print(m.hexdigest()) #得到hash值 此时校验的是 helloworld 。 #fc5e038d38a57032085441e7fe7010b0 # m=hashlib.md5() # m.update('hello'.encode('utf-8')) # m.update('world'.encode('utf-8')) # print(m.hexdigest()) # m1=hashlib.md5() m1.update('hellowor'.encode('utf-8')) m1.update('l'.encode('utf-8')) m1.update('d'.encode('utf-8')) print(m1.hexdigest()) #fc5e038d38a57032085441e7fe7010b0 和第一次得到的值是一样的 # name=input('user:>> ') # pwd=input('password:>> ') # m=hashlib.md5() # m.update(pwd.encode('utf-8')) # pwd=m.hexdigest() # # print(name,pwd) cryt_pwd='aee949757a2e698417463d47acac93df' pwds=[ 'alex3714', 'alex123', '123alex' ] def make_dic(pwds): dic={} for pwd in pwds: m=hashlib.md5(pwd.encode('utf-8')) #hashlib.md5可以接受一次值 dic[pwd]=m.hexdigest() return dic dic=make_dic(pwds) for pwd in dic: if dic[pwd] == cryt_pwd: print(pwd) #alex3714 import hashlib #加盐 m=hashlib.sha512() m=hashlib.md5('一行白鹭上青天'.encode('utf-8')) m.update('alex3714'.encode('utf-8')) m.update('两个黄鹂鸣翠柳'.encode('utf-8')) print(m.hexdigest()) #b018f53a1d2a6e85b3a750fd73123da7 import hmac #此模块是有是必须加盐 m=hmac.new('加盐'.encode('utf-8')) m.update('alex3714'.encode('utf-8')) print(m.hexdigest()) #ec9cab331d1f5b632581562832eb368a
10、subprocess 模块
import subprocess import time subprocess.Popen('uptime',shell=True) #第一个参数是字符串类型的命令,第二个参数是使用命令解释器解释第一个参数。程序并不会等待命令执行完毕,起一个子进程发送请求 所以会看到print的结果 print('----->主') time.sleep(1) #----->主 #22:44 up 9 days, 13:26, 12 users, load averages: 1.86 2.50 2.35 # import subprocess import time # obj=subprocess.Popen('uptime',shell=True, stdout=subprocess.PIPE, #正确输出传给PIPE管道 管道用的是一块共享内存 stderr=subprocess.PIPE, #错误输出传给PIPE管道 ) print(obj) #<subprocess.Popen object at 0x102a5f5c0> print('第1次:',obj.stdout.read()) #此时会等待命令运行完成后返回的结果在执行后面的代码 返回为bytes格式的 此时需要用decode转换成unicode bytes默认是系统的编码。 #第1次: b'22:51 up 9 days, 13:33, 12 users, load averages: 2.76 2.54 2.34\n' print('第2次:',obj.stderr.read()) #第2次: b'' print('---->主') print('第1次:',obj.stdout.read()) #只能取一次值 #第1次: b'' obj=subprocess.Popen('cat a.txt',shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) #print(obj.stdout.read()) #b'\xe6\xb5\x8b\xe8\xaf\x95' print(obj.stdout.read().decode("utf-8")) #测试 import subprocess #ls /etc ;pwdddd;ps aux 此时stdout和stderr都有结果 obj=subprocess.Popen('tasklist',shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) print(obj.stdout.read()) #b'' print(obj.stderr.read().decode("utf-8")) #/bin/sh: tasklist: command not found #了解 import subprocess #tasklist | findstr python obj=subprocess.Popen('ps -ef | grep python',shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) print(obj.stdout.read().decode("utf-8")) #501 40028 40023 0 11:06PM ?? 0:00.00 /bin/sh -c ps -ef | grep python #501 40030 40028 0 11:06PM ?? 0:00.00 grep python #第二种方式 模拟shell的管道 | obj1=subprocess.Popen('ps -ef',shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) obj2=subprocess.Popen('grep python',shell=True, stdin=obj1.stdout, #grep python 接收obj1 stdout输出的结果 stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) print(obj2.stdout.read().decode("utf-8")) #501 40103 40094 0 11:09PM ?? 0:00.01 grep python
二、面向对象基础
1、类的定义与使用
''' 1、面向过程与面向对象 面向过程:核心是过程二字,过程即解决问题的步骤,就是先干什么再干什么 基于该思想写程序就好比在设计一条流水线,是一种机械式的思维方式 优点:复杂的过程流程化,进而简单化 缺点:扩展性差 面向对象:核心是对象二字,对象是特征与技能的结合体 基于该思想编写程序就好比在创造一个世界,世界是由一个个对象组成。 优点:可扩展性强 缺点:编程复杂高,容易出现过度设计 2、类 对象是特征与技能的结合体,类就是一系列对象相似的特征与技能的结合体 在现实世界中:一定是先有的一个个具体存在的对象,后总结出的类 在程序中:一定保证先定义类,后产生对象 3、站在老男孩学校的角度 现实中的对象: 对象1: 特征 学校=老男孩 名字=李三炮 性别=男 年龄=18 技能 学习 选课 对象2: 特征 学校=老男孩 名字=张铁蛋 性别=女 年龄=38 技能 学习 选课 对象3: 特征 学校=老男孩 名字=武大郎 性别=男 年龄=28 技能 学习 选课 对象4: 特征 学校=老男孩 名字=egon 性别=男 年龄=18 技能 教学 现实中的老男孩学生类: 老男孩学生类 相似的特征 学校=老男孩 相似的技能 学习 选课 ''' # 类体代码在类的定义阶段就会立刻执行, lass Student: school='oldboy' def learn(self): print('is learning') def choose_course(self): print('choose course') # print('====run') print(Student) #<class '__main__.Student'> print(Student.__dict__) #{'__module__': '__main__', 'school': 'oldboy', 'learn': <function Student.learn at 0x102247620>, 'choose_course': <function Student.choose_course at 0x1022476a8>, '__dict__': <attribute '__dict__' of 'Student' objects>, '__weakref__': <attribute '__weakref__' of 'Student' objects>, '__doc__': None} #查看 print(Student.school) #数据属性 #oldboy print(Student.learn) #函数属性 #<function Student.learn at 0x102247620> #增加 Student.country='China' print(Student.country) #China #修改 Student.school='Oldboy' print(Student.school) #Oldboy #删除 del Student.country #print(Student.country) print(Student.learn) #<function Student.learn at 0x102247620> Student.learn('xxxxx') #is learning
2、对象的定义与使用
class Student: school='oldboy' #stu1,'李三炮','男',18 def __init__(self,name,sex,age): #在调用类时会自动触发执行 self.Name=name self.Sex=sex self.Age = age #stu1.Name='李三炮' #stu1.Sex='男' #stu1.Age=18 def learn(self): print('is learning') def choose_course(self): print('choose course') #调用类的过程又称之为实例化:stu1=Student('李三炮','男',18) #1、得到一个返回值,即对象,该对象是一个空对象stu1 #2、Student.__init__(stu1,'李三炮','男',18) stu1=Student('李三炮','男',18) print(stu1.__init__) #<bound method Student.__init__ of <__main__.Student object at 0x102a44940>> print(stu1.__dict__) #{'Name': '李三炮', 'Sex': '男', 'Age': 18} print(stu1.Name,stu1.Age,stu1.Sex) #李三炮 18 男 stu2=Student('张铁蛋','女',38) stu3=Student('武大郎','男',28) print(stu2.__dict__) #{'Name': '张铁蛋', 'Sex': '女', 'Age': 38} print(stu3.__dict__) #{'Name': '武大郎', 'Sex': '男', 'Age': 28} print(stu1,stu2,stu3) #<__main__.Student object at 0x101a449b0> <__main__.Student object at 0x101a44a20> <__main__.Student object at 0x101a44a58> print(stu2.Name) #张铁蛋
3、属性的查找和绑定方法
x=1 class Student: school='oldboy' # Name='xxx' def __init__(self,name,sex,age): #在调用类时会自动触发执行 self.Name = name self.Sex = sex self.Age = age #stu1.Name='李三炮' #stu1.Sex='男' #stu1.Age=18 def learn(self,x,y): print('%s is learning' %self.Name) print(x,y) def choose_course(self): print('choose course') def commit_hw(): print('commit homework') #1、查找一个对象的属性顺序是:先找对象自己的__dict__,再找类的__dict__ stu1=Student('李三炮','男',18) print(stu1.__dict__) #{'Name': '李三炮', 'Sex': '男', 'Age': 18} print(stu1.Name) #李三炮 print(stu1.school) #oldboy #print(stu1.x) #AttributeError: 'Student' object has no attribute 'x' stu1=Student('李三炮','男',18) stu2=Student('张铁蛋','女',38) stu3=Student('武大郎','男',28) # 2、类的数据属性是所有对象共享,所有对象都指向同一个内存地址 stu1.school='xxx' Student.school='Oldgirl' print(Student.school,id(Student.school)) #Oldgirl 4339288416 print(stu1.school,id(stu1.school)) #xxx 4331010344 print(stu2.school,id(stu2.school)) #Oldgirl 4339288416 print(stu3.school,id(stu3.school)) #Oldgirl 4339288416 # 3、类中定义的函数是绑定给对象使用: # 3.1:不同对象就是不同绑定方法 # 3.2:绑定给谁,就应该由谁来调用,谁来调用就会把谁当做第一个参数传给对应的函数 print(Student.learn) #<function Student.learn at 0x101a47730> print(stu1.learn) #<bound method Student.learn of <__main__.Student object at 0x101a44a58>> print(stu2.learn) #<bound method Student.learn of <__main__.Student object at 0x101a44a20>> print(stu3.learn) #<bound method Student.learn of <__main__.Student object at 0x101a44a90>> stu1.learn(1,2) #Student.learn(stu1,1,2) #李三炮 is learning #1 2 stu2.learn(1,3) # 张铁蛋 is learning # 1 3 stu3.learn(1,4) #武大郎 is learning #1 4 print(Student.learn) #<function Student.learn at 0x102a27730> #stu1.commit_hw() #TypeError: commit_hw() takes 0 positional arguments but 1 was given
4、小练习
class Teacher: school='oldboy' count=0 def __init__(self,name,sex,age,level,salary): self.name=name self.sex=sex self.age=age self.level=level self.salary=salary Teacher.count+=1 def teach(self): print('%s is teaching' %self.name) t1=Teacher('egon','male',18,10,3000) t2=Teacher('alex','female',38,9,30000) t3=Teacher('wxx','female',28,10,30000) print(t1.count) print(t2.count) print(t3.count) # 3 # 3 # 3
5、类即类型
l=[1,2,3,4] #l=list([1,2,3,4]) print(type(l)) #<class 'list'> l1=list([1,2,3,4]) l2=list([1,2,3,4]) print(id(l1)) #4339305672 print(id(l2)) #4339305736 print(l1.append) #<built-in method append of list object at 0x102a48cc8> #l1.append(5) #list.appent(l1,5) list.append(l1,5) print(l1) #[1, 2, 3, 4, 5]
6、对象之间的交互
class Garen: camp='demacia' def __init__(self,nickname,life_value,aggresivity): self.nickname=nickname self.life_value=life_value self.aggresivity=aggresivity def attack(self,enemy): enemy.life_value-=self.aggresivity class Riven: camp = 'Noxus' def __init__(self, nickname, life_value, aggresivity): self.nickname = nickname self.life_value = life_value self.aggresivity = aggresivity def attack(self, enemy): enemy.life_value -= self.aggresivity def fire(self,enemy): enemy.life_value-=100 g1=Garen('草丛猥琐男',1000,100) r1=Riven('猛男雯雯',200,500) print(r1.life_value) #200 g1.attack(r1) print(r1.life_value) #100
7、从代码级别看面向对象
#1、在没有学习类这个概念时,数据与功能是分离的 def exc1(host,port,db,charset,sql): conn=connect(host,port,db,charset) res=conn.execute(sql) return res def exc2(host,port,db,charset,proc_name) conn=connect(host,port,db,charset) res=conn.call_proc(prco_name) return res #每次调用都需要重复传入一堆参数 exc1('127.0.0.1',3306,'db1','utf8','select * from tb1;') exc2('127.0.0.1',3306,'db1','utf8','存储过程的名字') exc1('127.0.0.1',3306,'db1','utf8','select * from tb2;') #2、在没有学习类这个概念时,数据与功能是分离的 host='127.0.0.1' port=3306 db='db1' charset='utf-8' x=1 y=2 def exc1(sql): conn=connect(host,port,db,charset) res=conn.execute(sql) return res def exc2(proc_name) conn=connect(host,port,db,charset) res=conn.call_proc(prco_name) return res def func1(): print(x) print(y) def func2(): print(x) print(y) #每次调用都需要重复传入一堆参数 exc1('select * from tb1;') exc2('utf8','存储过程的名字') exc1('select * from tb2;') func() class Mysqlhandle: def __init__(self,host,port,db,charset='utf-8'): self.host=host self.port=port self.db=db self.charset=charset self.conn=connect(host,port,db,charset) def exc1(self,sql): return self.conn.execute(sql) def exc2(self,proc_name) return self.conn.call_proc(prco_name) obj1=Mysqlhandle('127.0.0.1',3306,'db1') obj1.exc1('select * from t1') obj1.exc1('select * from t2') obj1.exc1('select * from t3') obj2=Mysqlhandle('10.10.10.9',3306,'db2') obj2.exc1('select * from t1 where id > 3')