一、《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 = dbself.dbfilename = dbfilenameself.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 syssys.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' ),21field = input()db[key] = reckey = input()return dbif __name__ == '__main__':from initdata import db# dbpath=r'D:\pythonProject\project_hack\testDB'writeDB = WSave(db)# writeDB.storeDB()db=writeDB.loadDbase()import pprintpprint.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 = nameself.age = ageself.pay = payself.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=nameself.age=ageself.pay=payself.job=jobdef 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 = nameself.age = ageself.pay = payself.job = jobdef 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 = nameself.age = ageself.pay = payself.job = jobdef 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 shelvebob = 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:breaktry: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 showinfodef 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 entrieswindow =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] = entButton(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 windowdef 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 Personrecord = Person(name="?",age="?")for field in fieldnames:setattr(record,field,eval(entries[field].get()))db[key] = recordif __name__ == '__main__':import shelvedb =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 fontsizefontsize +=2mainLabel.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代码

运行:

《Python编程》第一章:先睹为快相关推荐

  1. Python入门——第一章 python编程基础

    Python入门 文章目录 Python入门 第一章 python编程基础 1.1 基本输入输出 1.1.1使用print()函数进行简单输出 chr()函数 print()输出到指定文件 print ...

  2. 《HeadFirst Python》第一章学习笔记

    对于Python初学者来说,舍得强烈推荐从<HeadFirst Python>开始读起,这本书当真做到了深入浅出,HeadFirst系列,本身亦是品质的保证.这本书舍得已在<Pyth ...

  3. python 机器学习第一章

    机器学习是一门能够发掘数据价值的算法和应用,是计算机科学中最激动人心的一个领域之一. 接下来的时间,开始学习吧! python机器学习第一章 1.机器学习方法分为三类:监督学习,无监督学习,强化学习. ...

  4. Python绝技第一章 入门 python3实现密码破解

    前言 对我而言,武术的非凡之处在于它的简单.简单的方法也是正确的方法,同时武术也没有什么特别之处.越接近武术的真谛,招式表现上浪费越少 简介 python 绝技 第一章是python入门语法,两个需要 ...

  5. 【李刚-21天通关Python】第一章:Python入门与字符串

    [李刚-21天通关Python]第一章:Python入门与字符串 第一章:Python入门与字符串 数据类型 字符串 运算符 实操:简易计算器 & 进制转换 章节分篇链接: [李刚-21天通关 ...

  6. Python Cookbook --第一章:数据结构和算法(1)

    问题1:现在有一个包含N个元素的元组或者是序列,怎样将它里面的值解压后同时赋值给N个变量? >>> p = (4,5) >>> x,y = p >>&g ...

  7. 使用java实现面向对象编程第十章嗖嗖移动业务大厅项目_ACCP6.0使用Java实现面向对象编程-第一章.ppt...

    ACCP6.0使用Java实现面向对象编程-第一章 练习--用类图设计Dog和Penguin类 需求说明: 运用面向对象思想抽象出Dog类和Penguin类,画出对应类图 根据类图编写Dog类和Pen ...

  8. Python计算机视觉编程 第一章 基本的图像操作和处理

    第一章 基本的图像操作和处理 1.1 PIL:Python图像处理类库 1.1.1转换图像格式 1.1.2创建缩略图 1.1.3复制和粘贴图像区域 1.1.4调整尺寸和旋转 1.2Matplotlib ...

  9. python第一章笔记_head first python(第一章)–学习笔记

    head first python(第一章)--学习流程图 1.安装python 这里是用python3的,除了windows之外,linux和macos都自带了,只是版本没有这么新. 举例:cent ...

  10. 廖雪峰python教程——第一章 Python基础

    第一章 Python基础 一.数据类型和变量 Python的数据类型包括整数.浮点数.字符串.布尔值.空值.变量.常量等.其中整数可以表示任意大小的整数:空值是Python里一个特殊的值,用None表 ...

最新文章

  1. 计算机视觉训练模型效果不佳怎么破?
  2. Codeforces757E.Bash Plays With Functions(积性函数 DP)
  3. RxJava2学习笔记(3)
  4. Android中设置输入法为数字输入
  5. 验证控件;正则表达式;
  6. Druid的Segment Balance及其代价计算函数分析
  7. MagicDraw UML 16.8 安装教程(2)-破解补丁
  8. Luogu2606[ZJOI2010] 排列计数
  9. python 基础语法梳理(二)
  10. GB35114---SM3withSM2证书生成及读取(一)
  11. LA 4670 Dominating Patterns
  12. 第21节 ACL——控制路由器上接口大门的进出规则
  13. mac zoc ssh工具
  14. shazam 音频指纹 听歌识曲 原理(附代码)
  15. USB驱动开发(五)之程序设计
  16. C# register
  17. 负载测试中极限负载_负载测试准则
  18. 学Java到底用什么电脑好呢?
  19. js计算出来的文件md5值跟java计算出来的不一致
  20. python+selenium爬虫,使用selenium爬取热门微博数据

热门文章

  1. 计算机网络原理 自考(五)
  2. Redis限流接口防刷
  3. 关于Android蓝牙串口通信那点破事
  4. 拼多多直播场控互动控场软件 免费 下载免费试用
  5. 三大运营商NB-IoT网络基站覆盖情况
  6. LabVIEW 2020入门(一)
  7. python正则匹配括号以及内容_【Python】正则表达式匹配最里层括号的内容
  8. tf.gather tf.gather_nd 和 tf.batch_gather 使用方法
  9. 时滞电力系统matlab,基于Wirtinger不等式的时滞电力系统稳定性判定方法
  10. 2018ICPC区域赛总结