《Python编程》第一章:先睹为快

一、《Python编程》的第一章综述

主要从数据(记录)的表示出发,讲述数据(记录)存储(内存、pickle、shelves),包括:格式化、持久化、图形化(GUI,tkinter)、控制台交互、OOP;最后还从Web界面引出CGI基础;

二、表示数据(记录)

1.List来表示数据记录(字符串基础

#定义一个列表
bob = ['Bob Smith',42,30000,'software']
sue = ['Sue Jones',45,40000,'hardware']
#获取姓名、薪水
print(bob[0],sue[2])
#获取姓,split()分割,不传参数及是以空格分割;举例:bob[0].split("b")---->结果:['Bo',' Smith'],注意空格在第二个元素中;
print(bob[0].split())#结果:['Bob', 'Smith']
print(bob[0].split()[-1])
#给sue加薪25%
sue[2] *=1.25
print(sue)#['Sue Jones', 45, 50000.0, 'hardware']
#-----------------------------------------------------------------------------------------------------------
#创建一个新列表的将bob与sue存储在一起;
people = [bob, sue]
for person in people:
    print(person)
#使用索引层层取值
print(people[1][0])
#打印姓氏,每个人涨工资25%
for person in people:
    print(person[0].split()[0])
    person[2] *=1.25
#检测薪资:
for person in people:print(person[2])
#收集薪资^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#列表解析:
pays =[ person[2] for person in people ]
print(pays)
#map:map(function, iterable, ...);function -- 函数;iterable -- 一个或多个序列;
pays =map((lambda x: x[2]), people)#返回迭代器对象<map object at 0x007BB2E0>
print(list(pays))
#生成器表达式,sum为内建函数
#sum(__iterable)
print(sum(person[2] for person in people))
#为people列表中添加元素
people.append(['Tom',50,0,None])
print(len(people),people[-1][0],sep=",")

2.Field标签

#使用关键字=索引号,将列表中的字段关联
NAME,AGE,PAY = range(3)
bob = ['Bob Smith',42,30000]
print(bob[NAME])

#但是上面的也不是长久之计,数据变了,这个字段名称就得维护;下面提供更优de方式:
bob = [['name','Bob Smith'],['age',42],['pay',10000]]
sue = [['name','Sue Jones'],['age',29],['pay',20000]]
people = [bob, sue]
#上面也没有从根本上解决问题,还是要通过索引来取值;只是知道其字段意思;
for person in people:
    print(person[0][1],person[2][1],sep=":")#name:pay
#更优de方式,使用元组赋值来拆开名/值对:
for person in people:
    for (name,value) in person :
        if name =='name':print(value)#寻找特定字段,这里举例name;还可以age、pay
#将上面得元组赋值拆分名/值对de方式封装成函数:
def field(record,label):
    for(fname,fvalue) in record:
        if fname == label:
            msg =label+":"+str(fvalue)
            return msg
for person in people:
    print(field(person,"age"))

3.dict来表示数据记录

#使用字典:
bob = {'name':'Bob Smith', 'age':42, 'pay':30000, 'job': 'dev'}
sue = {'name':'Sue Jnoes', 'age':56, 'pay':50000, 'job': 'pre'}
print(bob['name'])
#其他建立字典的方法:dict(key=value,……)
bob = dict(name='Bob Smith',age=42,pay=30000,job='dev')
sue = dict(name='Sue Jnoes',age=35,pay=35000,job='pre')
print(bob)
print(sue)
#一次一个字段填写字典;
sue={}
sue['name']='Sue Jones'
sue['age']=45
sue['pay']=5600
sue['job']='pre'
print(sue)
#使用zip函数将key/value列表链在一起:
names=['name','age','pay','job']
values=['Sue Jones',45,56000,'pre']
sue=dict(zip(names,values))#{'name': 'Sue Jones', 'age': 45, 'pay': 56000, 'job': 'pre'}
print(list(zip(names,values)))#[('name', 'Sue Jones'), ('age', 45), ('pay', 56000), ('job', 'pre')]
print(sue)
#使用dict的fromkeys来初始化所有key的value,只不过这些value都是一个值(可用于初始化字典):
data_keys=('name','age','job','pay')
record = dict.fromkeys(data_keys,'?')
print(record)#{'name': '?', 'age': '?', 'job': '?', 'pay': '?'}
#88888888888888888888888888888888888888888888888888888888888888888888888888888888
#同样列表与字典结合;
bob = {'name':'Bob Smith', 'age':42, 'pay':30000, 'job': 'dev'}
sue = {'name':'Sue Jnoes', 'age':56, 'pay':50000, 'job': 'pre'}
people = [bob,sue]
for person in people:
    print(person['name'],person['age'],person['pay'],sep=":")
#列表解析
names=[person['name'] for person in people]
print(names)
#map
print(list(map((lambda x:x['name']),people)))
#sum
print(sum(person['pay'] for person in people))
#奇妙的是:列表解析和按需生成器表达式,可以达到sql的效果:
thing = [rec['name'] for rec in people if rec['age'] >=45]
print(thing)#['Sue Jnoes']
thing1=[(rec['pay']**2 if rec['age']>45 else rec['pay']) for rec in people]
print(thing1)
#字典在python中是常见的对象,使用一般的方式更新、访问:
for person in people:
    print(person['name'].split()[0])
    person['pay'] *=1.25
t=[person['pay'] for person in people]
print(t)
###################################################################################
#嵌套结构
bob2={
    'name':{'first':'Bob','last':'Smith'},
    'age':42,
    'job':['software','writing'],
    'pay':(40000,50000)
}
#上面的通过索引两层就可访问数据;
#全部的工作:
for job in bob2['job']:print(job)
bob2['job'].append('tester')#添加新工作
print(bob2)
#################################################################################
#字典的字典
bob = dict(name='Bob Smith',age=42,pay=30000,job='dev')
sue = dict(name='Sue Jnoes',age=35,pay=35000,job='pre')
db = {}
db["bob"] = bob
db["sue"] = sue
print(db)#{'bob': {'name': 'Bob Smith', 'age': 42, 'pay': 30000, 'job': 'dev'}, 'sue': {'name': 'Sue Jnoes', 'age': 35, 'pay': 35000, 'job': 'pre'}}
import pprint
pprint.pprint(db)#打印出更易于清晰的格式
#{'bob': {'age': 42, 'job': 'dev', 'name': 'Bob Smith', 'pay': 30000},
# 'sue': {'age': 35, 'job': 'pre', 'name': 'Sue Jnoes', 'pay': 35000}}
#访问字典的字典:
for key in db:
    print(key,'=>',db[key]['name'])
#要么使用迭代字典的值集合来直接访问:
for record in db.values():print(record)
#使用迭代字典的值集合来直接访问记录:
x=[db[key]['name'] for key in db]
print(x)
#遇上等效:
x=[rec['name'] for rec in db.values()]
print(x)
#类似sql的查询:
tt=[rec['name'] for rec in db.values() if rec['age'] >=5]
print(tt)
目前为止,上面所见到的对象都是暂时的;他们只是保存在内存当中;并会随着我们退出python或者创建他们的python程序而烟消云散;为了使其永久化,它们需要保存在某种类型的文件中;

三、持久化存储数据(记录)

1.使用格式化文件

在程序运行时保存数据的一种方法---》是把所有数据以格式化的方式写入一个简单的文本文件中,要用时,在取出来重构
class WSave:

    def __init__(self,db,dbfilename = 'people-file'):

        self.db = db
        self.dbfilename = dbfilename
        self.ENDDB = 'enddb'
        self.ENDREC = 'endrec'
        self.RECSEP = '=>'

    def storeDB(self):
        '''
        将数据库格式化保存为普通文件
        :return:
        '''
        with open(self.dbfilename,'w') as dbfile:
            for key in self.db:
                print(key,file=dbfile)
                for (key,value) in self.db[key].items():
                    #下面的方式==等效于==》》print(key+"=>"+repr(value),file=dbfile)
                    dbfile.write(key+"=>"+repr(value)+"\n")#repr() 函数将对象转化为供解释器读取的形式
                    # print(key + self.RECSEP + repr(value), file=dbfile)
                print(self.ENDREC, file=dbfile)
            print(self.ENDDB, file=dbfile)
    def loadDbase(self):
        '''
        将文件中的数据解析,重构db
        :return:
        '''
        dbfile = open(self.dbfilename)
        import sys
        sys.stdin = dbfile#sys.stdin:标准输入
        db = {}
        key = input()
        while key != self.ENDDB:
            rec = {}
            field = input()
            while field !=self.ENDREC:
                name, value = field.split(self.RECSEP)
                rec[name] = eval(value)#函数用来执行一个字符串表达式,并返回表达式的值:eval( '3 * 7' ),21
                field = input()
            db[key] = rec
            key = input()
        return db

if __name__ == '__main__':
    from initdata import db
    # dbpath=r'D:\pythonProject\project_hack\testDB'
    writeDB = WSave(db)
    # writeDB.storeDB()
    db=writeDB.loadDbase()
    import pprint
    pprint.pprint(db)
    for key in db:
        print(key,"=>\n",db[key])
    print(db['sue']['name'])

2.使用pickle文件

#pickle包的初衷:可以将任意类型的python数据转化成可以保存在文件中的格式
#pickle模块将内存中的python对象转化成序列化的字节流;这是一种可以写入任何类似文件对象的字节串;;;
# pickle模块也可以根据序列化的字节流重新构建原来内存中的对象:转换成原来的对象;
# pickle模块取代了专有的数据格式;pickle感觉像XML的表达方式;但是,它是Python专用的方式并且比较容易编写代码
from initdata import db#最初创建的数据
import pickle
dbfile = open('people-file', 'wb')#二进制写
#已字节流写入文件,而非字符串
pickle.dump(db,dbfile)
dbfile.close()

dbfile1 = open('people-file', 'rb')#二进制读
#字节流重新构建原来内存中的对象
db=pickle.load(dbfile1)
dbfile1.close()
import pprint
pprint.pprint(db)

#上面的例子都有一个缺陷,每更新一条记录,就需要读出和重新写入整个数据库;
# 我们可以通过一条记录到一个普通文件的方式来改进;
from initdata import bob,sue,tom #最初创建的数据
import pickle
#每个文件一个名称记录一条数据;
for (key, record) in [('bob',bob),('tom',tom),('sue',sue)]:
    recfile = open(key+'.pkl','wb')
    pickle.dump(record,recfile)
    recfile.close()
import glob#glob该方法返回所有匹配的文件路径列表
for filename in glob.glob('*.pkl'):
    recfile = open(filename,'rb')
    record = pickle.load(recfile)
    print(filename,'=>\n',record)

#修改一条记录后,在写入
dbfile = open('sue.pkl','rb')
v = pickle.load(dbfile)
v['pay'] *= 1.10
dbfile.close()
new_dbf= open('sue.pkl','wb')
pickle.dump(v,new_dbf)
new_dbf.close()

3.使用shelves

#更高级的库:shelves;用键来访问记录;shelve系统自动分隔存储记录,并且只获取和更新访问和修改的记录;
# shelve使用起来很像一堆只存储一条记录的pickle 文件;但更容易编辑;
from initdata import bob,sue
import shelve
db = shelve.open('people-shelve')
db['bob'] = bob
db['sue'] = sue
db.close()
#执行上面的代码后,出现了people-shelve.bak;people-shelve.dat;people-shelve.dir目录;
# 千万不要删除(它们就是你的数据库)
#shelve就像一个持久化的字典。
db = shelve.open('people-shelve')
for key in db:
    print(key,'=>\n',db[key])
db.close()
#修改(在内存中修改,在重新对键进行赋值来更新shelve)、添加;
db = shelve.open('people-shelve')
sue = db['sue']
sue['pay'] *=1.50#内存中修改后
db['sue'] = sue#重新对键进行赋值
from initdata import tom
db['tom'] = tom#添加新记录
db.close()

四、走进OOP

#OOP:python一切皆对象;这是一种程序设计的思路:Structure(结构)、Encapsulation(封装)、Customiztion(定制)
#Structure(结构):类既提供了程序单元将逻辑与数据合并在单独的包中,又提供了一个层级结构;使得代码更容易组织从而防止代码冗余;
# Encapsulation(封装):我们可以自由的更改方法的实现而不会破坏调用者的代码;
# Customiztion(定制):通过编写新的子类就可以扩展和定制类,同时不会更改或破坏已工作的代码;

1.类表示数据

#1.类记录数据---》对象的属性取代了字典的key;
class Person:
    def __init__(self,name,age,pay = 0, job = None):
        self.name = name
        self.age = age
        self.pay = pay
        self.job = job
if __name__ == '__main__':
    bob = Person('Bob Smith',42,30000,'software')
    sue = Person('Sue Jones',45,40000,'harware')
    print(bob.name,sue.pay)

2.类添加行为与继承

#2.类添加行为(函数)---》数据与行为的结合,函数(或者说方法)提供了解释和更新数据的逻辑(称之为面向对象,因为它们总是处理对象的数据/属性)
class Person:
    def __init__(self,name,age,pay=0,job=None):
        self.name=name
        self.age=age
        self.pay=pay
        self.job=job
    def lastName(self):
        return self.name.split()[-1]

    def giveRaise(self,percent):
        self.pay *= (1.0+percent)
0000000000000000000000000000000000000000000000000000000000000
#3.类的继承--》继承后子类包含了父类所有的属性、和函数;子类可以重新覆盖父类中的函数
class Manager(Person):
    def giveRaise(self,percent,bonus= 0.1):
        self.pay *=(1.0+bonus+percent)

3.类格式化显示、增强方法

#4.格式化显示:当对象需要整体的打印输出时,该方法可以返回对象的格式化字符串
class Person:
    def __init__(self, name, age, pay=0, job=None):
        self.name = name
        self.age = age
        self.pay = pay
        self.job = job

    def lastName(self):
        return self.name.split()[-1]

    def giveRaise(self, percent):
        self.pay *= (1.0 + percent)
    #格式化显示:当对象需要整体的打印输出时,该方法可以返回对象的格式化字符串;
    def __str__(self):
        return "<%s ==> %s>" % (self.__class__.__name__, [self.name, self.age, self.pay, self.job])
#增强方法:和上面重写函数相比,这种方式不但可以降低代码冗余,而且实践中尤其利于启动父类的构造函数
class Manager1(Person):
    def giveRaise(self,percent,bonus= 0.1):
        Person.giveRaise(self,percent+bonus)

tom = Manager1('Tom iThing',25,150000)
print(tom)#<Manager1 ==> ['Tom iThing', 25, 150000, None]>

4.自定义构造函数

#5.#自定义构造函数

class Person:
    def __init__(self, name, age, pay=0, job=None):
        self.name = name
        self.age = age
        self.pay = pay
        self.job = job

    def lastName(self):
        return self.name.split()[-1]

    def giveRaise(self, percent):
        self.pay *= (1.0 + percent)

    def __str__(self):
        return "<%s ==> %s>" % (self.__class__.__name__, [self.name, self.age, self.pay, self.job])

class Manger(Person):
    # 自定义构造函数
    def __init__(self, name, age, pay):
        Person.__init__(self, name, age, pay,'manager')#这里使用的技巧就是明确调用父类的构造函数,job直接写死manager;

    def giveRaise(self,percent,bonus=0.1):
        Person.giveRaise(self,percent+bonus)
#下面看多态:
bob = Person('Bob Smith', 44)
sue = Person('Sue Joner',23,12000,'hardware')
tom = Manger('iThing Tom',29,150000)
for obj in (bob,sue,tom):
    obj.giveRaise(.10)
    print(obj)
#上面运行的结果是:
# <Person ==> ['Bob Smith', 44, 0.0, None]>
# <Person ==> ['Sue Joner', 23, 13200.000000000002, 'hardware']>
# <Manger ==> ['iThing Tom', 29, 180000.0, 'manager']>

5.对类增加shelves持久化

#6#增添持久化
#为了更明了,我将上面的两个class分别写在两个py文件中
from Person import Person
from Manager import Manager
import shelve

bob = Person('Bob Smith', 44)
sue = Person('Sue Joner',23,12000,'hardware')
tom = Manager('iThing Tom',29,1500000)

db = shelve.open('class-shelve')
db['bob'] = bob
db['sue'] = sue
db['tom'] = tom
db.close()

#上面将对象存储在了shelve数据库中;下面取出来,看看可以使用对象的函数不?
db0 = shelve.open('class-shelve')
for person in db0:
    print(db0[person])
bob=db0['bob']
print(bob.lastName())
tom=db0['tom']
tom.giveRaise(.20)
db0['tom']=tom
db0.close()
print(tom)

五、控制台交互

#shelve的控制台界面
import shelve
fieldnames = ('name','age','job','pay')
maxfield = max(len(f) for f in fieldnames)
db = shelve.open('class-shelve')

while True:
    key = input('\nKey? => ')
    if not key:break
    try:
        record = db[key]
    except:
        print('没有找到对应的数据记录')
    else:
        for field in fieldnames:
            print(field.ljust(maxfield),'=>',getattr(record,field))

六、GUI---->tkinter

tkinter包含超过20多种控件,多种获取用户的输入的方式,多行文本、画布、下拉菜单、单选和复选、滚动条等

访问寻求更多:https://www.runoob.com/python/python-gui-tkinter.html

#Tk():创建应用程序主窗口
#Frame():创建控件容器,可依附在窗口中
#TopLevel():创建弹出式窗口
#获取用户的输入:
from tkinter import *
from tkinter.messagebox import showinfo

def reply(msg):
    showinfo(title='Reply',message='Hello %s' % msg)
top = Tk()
top.title('Echo')#改变窗口title
top.iconbitmap('expand.ico')#改变图标

Label(top,text='Enter your name:').pack(side=TOP)
#使用Entry控件获取用户输入并在弹出对话框中加以显示
ent = Entry(top)
ent.pack(side=TOP)
#这里使用lambda来延迟对reply函数的调用;使输入数据得以传入,这是tkinter常用的编程模式;
# 如果不使用lamdba,reply方法在按钮创建时就会被调用,而不是等到按钮单击时;
btn = Button(top,text='Submit',command=(lambda :reply(ent.get())))
btn.pack(side=LEFT)

top.mainloop()
from tkinter import *
from tkinter.messagebox import showerror
import shelve
shelvename = 'class-shelve'
fieldnames = ('name','age','job','pay')

def makeWidgets():
    global entries
    window =Tk()
    window.title('People Shelve')
    form = Frame(window)
    form.pack()
    entries = {}
    for (ix,label) in enumerate(('key',)+fieldnames):
        lab = Label(form,text=label)
        ent = Entry(form)
        lab.grid(row=ix,column=0)#网格
        ent.grid(row=ix,column=1)
        entries[label] = ent
    Button(window, text="Fetch",command=fetchRecord).pack(side=LEFT)
    Button(window,text="Update",command=updateRecord).pack(side=LEFT)
    Button(window,text="Quit",command=window.quit).pack(side=RIGHT)
    return window

def fetchRecord():
    key = entries['key'].get()
    try:
        record = db[key]#使用键获取数据,并在GUI中展示
    except:
        showerror(title='Error',message='No such key!')
    else:
        for field in fieldnames:
            entries[field].delete(0,END)
            entries[field].insert(0,repr(getattr(record,field)))

def updateRecord():
    key = entries['key'].get()
    if key in db:
        record = db[key]
    else:
        from Person import Person
        record = Person(name="?",age="?")
    for field in fieldnames:
        setattr(record,field,eval(entries[field].get()))
    db[key] = record

if __name__ == '__main__':
    import shelve
    db =shelve.open(shelvename)
    window = makeWidgets()
    window.mainloop()
    db.close()
from tkinter import *
import random
fontsize = 30
colors = ['red','green','blue','yellow','orange','cyan','purple']
def onSpam():
    popup = Toplevel()
    color = random.choice(colors)
    Label(popup,text='Popup',bg='black',fg=color).pack(fill=BOTH)
    mainLabel.config(fg=color,bg=random.choice(colors))

def onFlip():
    mainLabel.config(fg=random.choice(colors))
    main.after(250, onFlip)

def onGrow():
    global fontsize
    fontsize +=2
    mainLabel.config(font=('arial',fontsize,'italic'))
    main.after(100,onGrow)

main = Tk()
mainLabel = Label(main,text='Fun Gui!',relief=RAISED)
mainLabel.config(font=('arial',fontsize,'italic'),fg='cyan',bg='navy')
mainLabel.pack(side=TOP,expand=YES,fill=BOTH)
Button(main,text='spam',command=onSpam).pack(fill=X)
Button(main,text='flip',command=onFlip).pack(fill=X)
Button(main,text='grow',command=onGrow).pack(fill=X)
Button(main,text='关闭',command=main.quit).pack(fill=X)
main.mainloop()

七、CGI基础

浏览器--服务器--后端逻辑;

特别注意:目录结构

1.服务器的简单代码

#-*-coding:utf-8-*-
import os,sys
from http.server import HTTPServer,CGIHTTPRequestHandler
webdir = "."#存放HTML和cgi脚本文件夹的所在
port = 80
os.chdir(webdir)#在HTML根目录中运行
srvraddr =('',port)#我的主机和端口
srvrobj = HTTPServer(srvraddr,CGIHTTPRequestHandler)
srvrobj.serve_forever()#永久守护进程运行

2.html代码

运行:

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

冷凝娇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值