入口函数 需要代码来模拟
对于很多编程语言来说,程序都必须要有一个入口,比如 C,C++,以及完全面向对象的编程语言 Java,C# 等。如果你接触过这些语言,对于程序入口这个概念应该很好理解,C 和 C++ 都需要有一个 main 函数来作为程序的入口,也就是程序的运行会从 main 函数开始。同样,Java 和 C# 必须要有一个包含 Main 方法的主类来作为程序入口。
而 Python 则有不同,它属于脚本语言,不像编译型语言那样先将程序编译成二进制再运行,而是动态的逐行解释运行。也就是从脚本第一行开始运行,没有统一的入口。
一个 Python 源码文件除了可以被直接运行外,还可以作为模块(也就是库)被导入。不管是导入还是直接运行,最顶层的代码都会被运行(Python 用缩进来区分代码层次)。而实际上在导入的时候,有一部分代码我们是不希望被运行的。
>>> __name__
'__main__'
if __name__ == "__main__":
main()
import
import turtle
# 需要使用 turtle.fd() 来使用
from turtle import *
# fd() 直接使用
eval() 代替 float()等函数
方法demo解释为:将字符串str当成有效的表达式来求值并返回计算结果。
可以把list,tuple,dict和string相互转化
a = "[[1,2], [3,4], [5,6], [7,8], [9,0]]"
b = eval(a)
b
Out[3]: [[1, 2], [3, 4], [5, 6], [7, 8], [9, 0]]
type(b)
Out[4]: list
a = "{1: 'a', 2: 'b'}"
b = eval(a)
b
Out[7]: {1: 'a', 2: 'b'}
type(b)
Out[8]: dict
a = "([1,2], [3,4], [5,6], [7,8], (9,0))"
b = eval(a)
b
Out[11]: ([1, 2], [3, 4], [5, 6], [7, 8], (9, 0))
数据类型 6种
程序设计是不允许出现歧义的,所以类型是确定的
数字 字符串 元组 列表 文件 字典
数字:整数,浮点数,复数
整数:没有范围;pow(2,100) 计算2的100次
0o 0O : 8进制;0x 0X : 16进制; 0b 0B : 二进制
浮点数:浮点计算单元;
e:表示10的次方,科学记数法
复数:z=a+bj a是实数部分,b是虚数部分 a,b都是浮点数
z.real 实数部分 z.imag 虚数部分
三者可以混合计算,计算结果为最宽的类型
互相转化:int() float() complex()
类型判断:type(x)
运算符号:/*-+
>>> 5//4
1
>>> 5/4
1.25
>>> 5%4
1
字符串
类型str ; 索引从0开始
输出“ ‘ / 使用反斜杠/来转义
最后一个的位置L-1;索引是-1
一个子集索引序列1:3,注意不包含3
# 加法+ 乘法*
>>> "asd"+"qwe"
"asdqwe"
>>> 3*"asd"
"asdasdasd"
常用函数
len() # 返回字符串的长度
str() # 大多数据类型可以转化成字符串
# 遍历字符串
for i in :
"\n" # 换行
元组
包含多个数据类型,逗号分割,元组可以空,外侧括号可以包括或者不包括
个元素存在先后顺序,可以索引;元组定义后不能更改,也不能删除;
类似于字符串的索引区间;
安全,但不灵活;如果灵活使用列表
列表
有序,索引;列表大学没有限制,随便修改;
列表的操作
# 字符串可以用 split() 来拆分成一个列表
>>> "s d f".split()
['s', 'd', 'f']
遍历列表:
list = ['html', 'js', 'css', 'python']
# 方法1
for i in list:
print ("序号:%s 值:%s" % (list.index(i) + 1, i))
# 方法2
for i in range(len(list)):
print ("序号:%s 值:%s" % (i + 1, list[i]))
# 方法3
for i, val in enumerate(list):
print ("序号:%s 值:%s" % (i + 1, val))
# 方法4 enumerate()函数的第二个参数只是改变了序号的起始值,并没有改变其他的东东
for i, val in enumerate(list, 2):
print ("序号:%s 值:%s" % (i + 1, val))
字典
无序的数据结构
创建字典:用大括号的形式
增加字典内容:通过中括号增加。dic["dd"] = asd
删除某一项:del dic["dd"]
字典的遍历:
for key in student:
for key in student.keys():
for value in student.values():
for item in student.items():
for item,value in student.items():
>>> d={'list':[1, 2, 3],1:123,'111':'python3','tuple':(4, 5, 6)}
>>> d
{'list': [1, 2, 3], 1: 123, '111': 'python3', 'tuple': (4, 5, 6)}
# 方法1
>>> for key in d:
print(str(key)+':'+str(d[key]))
list:[1, 2, 3]
1:123
111:python3
tuple:(4, 5, 6)
# 方法2
>>> for key in d.keys():
print(key)
list
1
111
tuple
# 方法3
>>> for value in d.values():
print (value)
[1, 2, 3]
123
python3
(4, 5, 6)
# 方法4
>>> for item in d.items():
print(item)
('list', [1, 2, 3])
(1, 123)
('111', 'python3')
('tuple', (4, 5, 6))
# 方法5
>>> for key,value in d.items():
print(key,value)
list [1, 2, 3]
1 123
111 python3
tuple (4, 5, 6)
判断一个键是否在字典中: in;not in
字典的标准操作符:- < > <= >= == != and or not;没有拼接和重复操作
词频统计问题:重复词语,概要分析,搜索引擎
import turtle
##全局变量##
#词频排列显示个数
count = 10
#单词频率数组-作为y轴数据
data = []
#单词数组-作为x轴数据
words = []
#y轴显示放大倍数-可以根据词频数量进行调节
yScale = 6
#x轴显示放大倍数-可以根据count数量进行调节
xScale = 30
################# Turtle Start ####################
#从点(x1,y1)到(x2,y2)绘制线段
def drawLine(t, x1, y1, x2, y2):
t.penup()
t.goto (x1, y1)
t.pendown()
t.goto (x2, y2)
# 在坐标(x,y)处写文字
def drawText(t, x, y, text):
t.penup()
t.goto (x, y)
t.pendown()
t.write(text)
def drawGraph(t):
#绘制x/y轴线
drawLine (t, 0, 0, 360, 0)
drawLine (t, 0, 300, 0, 0)
#x轴: 坐标及描述
for x in range(count):
x=x+1 #向右移一位,为了不画在原点上
drawText(t, x*xScale-4, -20, (words[x-1]))
drawText(t, x*xScale-4, data[x-1]*yScale+10, data[x-1])
drawBar(t)
#绘制一个柱体
def drawRectangle(t, x, y):
x = x*xScale
y = y*yScale#放大倍数显示
drawLine(t, x-5, 0, x-5, y)
drawLine(t, x-5, y, x+5, y)
drawLine(t, x+5, y, x+5, 0)
drawLine(t, x+5, 0, x-5, 0)
#绘制多个柱体
def drawBar(t):
for i in range(count):
drawRectangle(t, i+1, data[i])
################# Turtle End ####################
#对文本的每一行计算词频的函数
def processLine(line, wordCounts):
#用空格替换标点符号
line = replacePunctuations(line)
#从每一行获取每个词
words = line.split()
for word in words:
if word in wordCounts:
wordCounts[word] += 1
else:
wordCounts[word] = 1
#空格替换标点的函数
def replacePunctuations(line):
for ch in line:
if ch in "~@#$%^&*()_-+=<>?/,.:;{}[]|\'""":
line = line.replace(ch, " ")
return line
def main():
#用户输入一个文件名
filename = input("enter a filename:").strip()
infile = open(filename, "r")
#建立用于计算词频的空字典
wordCounts = {}
for line in infile:
processLine(line.lower(), wordCounts)
#从字典中获取数据对
pairs = list(wordCounts.items())
#列表中的数据对交换位置,数据对排序
items = [[x,y]for (y,x)in pairs]
items.sort()
#输出count个数词频结果
for i in range(len(items)-1, len(items)-count-1, -1):
print(items[i][1]+"\t"+str(items[i][0]))
data.append(items[i][0])
words.append(items[i][1])
infile.close()
#根据词频结果绘制柱状图
turtle.title('词频结果柱状图')
turtle.setup(900, 750, 0, 0)
t = turtle.Turtle()
t.hideturtle()
t.width(3)
drawGraph(t)
#调用main()函数
if __name__ == '__main__':
main()
#利用字典将两个通讯录文本合并为一个文本
def main():
ftele2=open('TeleAddressBook.txt','rb')
ftele1=open('EmailAddressBook.txt','rb')
ftele1.readline()#跳过第一行
ftele2.readline()
lines1 = ftele1.readlines()
lines2 = ftele2.readlines()
dic1 = {} #字典方式保存
dic2 = {}
for line in lines1:#获取第一个本文中的姓名和电话信息
elements = line.split()
#将文本读出来的bytes转换为str类型
dic1[elements[0]] = str(elements[1].decode('gbk'))
for line in lines2:#获取第二个本文中的姓名和电话信息
elements = line.split()
dic2[elements[0]] = str(elements[1].decode('gbk'))
###开始处理###
lines = []
lines.append('姓名\t 电话 \t 邮箱\n')
for key in dic1:
s= ''
if key in dic2.keys():
s = '\t'.join([str(key.decode('gbk')), dic1[key], dic2[key]])
s += '\n'
else:
s = '\t'.join([str(key.decode('gbk')), dic1[key], str(' ----- ')])
s += '\n'
lines.append(s)
for key in dic2:
s= ''
if key not in dic1.keys():
s = '\t'.join([str(key.decode('gbk')), str(' ----- '), dic2[key]])
s += '\n'
lines.append(s)
ftele3 = open('AddressBook.txt', 'w')
ftele3.writelines(lines)
ftele3.close()
ftele1.close()
ftele2.close()
print("The addressBooks are merged!")
if __name__ == "__main__":
main()
math random 库介绍
π:计算使用,蒙特卡洛方法。利用随机试验求解。在一个正方形里面抛洒随机点,然后用落在圆里面的点除以所有的抛洒点。
from random import random
from math import sqrt
from time import clock
DARTS = 1200
hits = 0
clock()
for i in range(1, DARTS):
x,y = random(), random()
dist = sqrt(x**2+y**2)
if dist <= 1.0:
hits = hits + 1
pi = 4*(hits/DARTS)
程序设计
3种结构:顺序,选择,循环
多分支结构:条件互斥的
异常处理 try ... except ...
try:
except <> :
except:
异常处理语句,else和finally
try:
except:
else: # try里面无异常执行
finally: # 都会执行。通信或者文件操作
实际例子
三个数字比较:
决策树:效率高,但代码成爆炸增长
顺序处理:逐个扫描,记录最大值,使用循环体,解决更复杂问题
内置函数: max(); 真正的程序员应该是借鉴
循环
for 固定循环次数 while 无固定次数
break 结束循环 continue 结束本次循环
-- 如果不知道多少个数字,for就局限了,哨兵方法;采用非空字符串这个方法来解决;
-- 输入的数字太多,可以转化到文件的输入方式
def main():
fileName = input("")
infile = open(fileName,"r")
sum = 0
count = 0
for line in infile:
sum = sum + eval(line)
count = count +1
print(sum/count)
main()
采用哨兵:
def main():
fileName = input("")
infile = open(fileName,"r")
sum = 0
count = 0
line = infile.readline()
while line != "":
sum = sum + eval(line)
count = count +1
line = infile.readline()
print(sum/count)
main()
如果是逗号分割的,csv文件; 多重循环
def main():
fileName = input("")
infile = open(fileName,"r")
sum = 0
count = 0
line = infile.readline()
while line != "":
for xStr in line.splite(","):
sum = sum + eval(xStr)
count = count +1
line = infile.readline()
print(sum/count)
main()
布尔操作 and or not
优先级:not and or
>>> a = input() or "sasd"
xcz
>>> a
'xcz'
函数
返回值
返回一个表达式:
def fun(x):
return x*x
返回多个值:
def sumDiff(x,y):
sum = x+y
diff = x-y
return sum,diff
s,d = sumDiff(1,2)
没有返回值,改变输入实参
列表输入后,是指向了新的数据,旧数据会被垃圾回收机制回收。
递归
字符串反转:
def reverse(s):
if s == "":
return s
else:
return reverse(s[1:]) + s[0]
文件
编码
常用编码: ASCII,128位
>>> ord('A')
65
>>> ord('a')
97
>>> chr(65)
'A'
>>> chr(97)
'a'
常用编码: Unicode,65536
常用编码: UTF-8, 可变长度的Unicode
常用编码: GBK,汉字内码扩展规范
python中字符串类型未编码
encode()
decode()
文件数据
文本文件,ASCII存储的文件
二进制文件,文件编码是变长的,解码方式不同
文件操作
打开文件
建立磁盘上的文件与程序中的对象相关联
通过相关的文件对象 获得
# open()
open("numbers.dat","r")
open("music.mp3","rb")
文件操作
读取,写入,定位,追加,计算
read() # 字符串:包含整个文件
readline() # 字符串:文件下一行内容
readlines() # 列表:字符串:以换行符结尾的内容
for i in range(5):
line = infile.readline()
print(line[:-1])
写入文件
write() # 文本数据或二进制数据块的字符串
writelines() # 字符串列表为参数
关闭文件
切断文件与程序的联系
写入磁盘,并释放文件缓冲区
文件遍历
file = open()
for line in file.readlines():
for line in file:
file.cloas()
文件拷贝
f1 = input().strip()
f2 = input().strip()
infile = open(f1,"r")
outfile = open(f2,"w")
coutLines = countChars = 0
for line in infile:
coutLines += 1
countChars +=len(line)
outfile.write(line)
infile.close()
outfile.close()
#根据数据文件在窗口中动态路径绘制
import turtle
def main():
#设置窗口信息
turtle.title('数据驱动的动态路径绘制')
turtle.setup(800, 600, 0, 0)
#设置画笔
pen = turtle.Turtle()
pen.color("red")
pen.width(5)
pen.shape("turtle")
pen.speed(5)
#读取文件
result=[]
file = open("data.txt","r")
for line in file:
result.append(list(map(float, line.split(','))))
print(result)
#动态绘制
for i in range(len(result)):
pen.color((result[i][3],result[i][4],result[i][5]))
pen.forward(result[i][0])
if result[i][1]:
pen.rt(result[i][2])
else:
pen.lt(result[i][2])
pen.goto(0,0)
if __name__ == '__main__':
main()
#利用字符串和列表将两个通讯录文本合并为一个文本
def main():
ftele1=open('TeleAddressBook.txt','rb')
ftele2=open('EmailAddressBook.txt','rb')
ftele1.readline()#跳过第一行
ftele2.readline()
lines1 = ftele1.readlines()
lines2 = ftele2.readlines()
list1_name = []
list1_tele = []
list2_name = []
list2_email = []
for line in lines1:#获取第一个文本中的姓名和电话信息
elements = line.split()
list1_name.append(str(elements[0].decode('gbk')))
list1_tele.append(str(elements[1].decode('gbk'))) #将文本读出来的bytes转换为str类型
for line in lines2:#获取第二个文本中的姓名和邮件信息
elements = line.split()
list2_name.append(str(elements[0].decode('gbk')))
list2_email.append(str(elements[1].decode('gbk')))
###开始处理###
lines = []
lines.append('姓名\t 电话 \t 邮箱\n')
#按索引方式遍历姓名列表1
for i in range(len(list1_name)):
s= ''
if list1_name[i] in list2_name:
j = list2_name.index(list1_name[i]) #找到姓名列表1对应列表2中的姓名索引位置
s = '\t'.join([list1_name[i], list1_tele[i], list2_email[j]])
s += '\n'
else:
s = '\t'.join([list1_name[i], list1_tele[i], str(' ----- ')])
s += '\n'
lines.append(s)
#处理姓名列表2中剩余的姓名
for i in range(len(list2_name)):
s= ''
if list2_name[i] not in list1_name:
s = '\t'.join([list2_name[i], str(' ----- '), list2_email[i]])
s += '\n'
lines.append(s)
ftele3 = open('AddressBook.txt', 'w')
ftele3.writelines(lines)
ftele3.close()
ftele1.close()
ftele2.close()
print("The address books are merged!")
if __name__ == "__main__":
main()
面向对象程序设计
class className[(父类名)] :
_init_ 构造函数,初始化对象各属性
_del_ 析构函数,销毁对象
# 找到GPA最高的学生
class Student:
def __init__(self, name, hours, qpoints):
self.name = name
self.hours = float(hours)
self.qpoints = float(qpoints)
def getName(self):
return self.name
def getHours(self):
return self.hours
def getQPoints(self):
return self.qpoints
def gpa(self):
return self.qpoints/self.hours
def makeStudent(infoStr):
name, hours, qpoints = infoStr.split("\t")
return Student(name, hours, qpoints)
def main():
# 打开输入文件
filename = input("Enter name the grade file: ")
infile = open(filename, 'r')
# 设置文件中第一个学生的记录为best
best = makeStudent(infile.readline())
# 处理文件剩余行数据
for line in infile:
# 将每一行数据转换为一个记录
s = makeStudent(line)
# 如果该学生是目前GPA最高的,则记录下来
if s.gpa() > best.gpa():
best = s
infile.close()
# 打印GPA成绩最高的学生信息
print("The best student is:", best.getName())
print("hours:", best.getHours())
print("GPA:", best.gpa())
if __name__ == '__main__':
main()
实例: 铅球飞行轨迹计算
# Projectile.py
from math import sin, cos, radians
class Projectile:
def __init__(self, angle, velocity, height):
#根据给定的发射角度、初始速度和位置创建一个投射体对象
self.xpos = 0.0
self.ypos = height
theta = radians(angle)
self.xvel = velocity * cos(theta)
self.yvel = velocity * sin(theta)
def update(self, time):
#更新投射体的状态
self.xpos = self.xpos + time * self.xvel
yvell = self.yvel - 9.8 * time
self.ypos = self.ypos + time * (self.yvel + yvell) / 2.0
self.yvel = yvell
def getY(self):
#返回投射体的角度
return self.ypos
def getX(self):
#返回投射体的距离
return self.xpos
写成库文件格式,被引入。
from Projectile import *
def getInputs():
a = eval(input("Enter the launch angle (in degrees):"))
v = eval(input("Enter the initial velocity (in meters/sec):"))
h = eval(input("Enter the initial height (in meters):"))
t = eval(input("Enter the time interval: "))
return a,v,h,t
def main():
angle,vel,h0,time = getInputs()
shot = Projectile(angle,vel,h0)
while shot.getY() >=0:
shot.update(time)
print("\nDistance traveled:{0:0.1f}meters.".format(shot.getX()))
if __name__ == "__main__":
main()
单下划线、双下划线、头尾双下划线说明:
_foo_: 定义的是特殊方法,一般是系统定义名字 ,类似 init() 之类的。
_foo: 以单下划线开头的表示的是 protected 类型的变量,即保护类型只能允许其本身与子类进行访问,不能用于 from module import *
__foo: 双下划线的表示的是私有类型(private)的变量, 只能是允许这个类本身进行访问了。