day6 (常用模块和面向对象基础)

一、常用模块

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模块

示例文件

<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>
View Code

实践

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模块

[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
View Code

示例

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

 

posted @ 2018-01-16 21:18  xglv  阅读(308)  评论(0编辑  收藏  举报