• 1. Python简介
  • 2. Python 基础篇 -Life Is Short You Need PythonPython 简介Python是一种开源的 、解析性的,面向对象的编程语言。 Python使用一种优雅的语法,可读性强 Python支持类和多层继承等的面向对象编程技术。 Python可运行在多种计算机平台和操作系统中,如unix,windows,MacOS,OS/2等等
  • 3. 使用python安装python, 请参阅:http://www.python.org运行python脚本: 交互式运行(在Windows平台下有GUI界面) 执行python脚本文件 在Linux/UNIX环境下运行程序 。 在python头部加一行:#! /usr/local/bin/python chmod +x myfile.py ./myfile.py (当然也可以直接以python myfile 方式执行)
  • 4. 快速开始简单语句print “hello world” 计算器 1+1 格式化字符串 print "The total is %0.2f" %56.3598
  • 5. 注释 和 模块注释 # 我是注释 “”“ 我的注释 ”“” 模块 import sys sys.exit()
  • 6. Python的数据类型变量的定义。在python中,变量的类型是由赋给它的数值定义的。 q = 7 #q其为数值型变量 q = “Seven” #q为字符串型变量 基本数据类型:字符串,整数,浮点数,虚数,布尔型。 集合类型:列表(List),元组(Tuple),字典(Dictionary或Hash)
  • 7. Python的数据类型列表(List)List的定义。 aList = [23] 或者 bList = [1,2,3] List的使用。可以像c语言中数据一样引用list中的元素。 print bList[1] List常用操作:append, del, + ,*, len(list) [0] * 5
  • 8. Python的数据类型:列表(方法)列表对象支持的方法(演示) append(x) count(x) :X在List中的个数 extend(L) Index(x) insert(i,x) pop(x) remove(x) reverse() sort()
  • 9. Python的数据类型:元组(Tuple)Tuple的定义 aTuple = (1, 3, 5) print aTuple 元组可以用方括号括起下标做索引 元组一旦创建就不能改变 列表大部分操作同样适用于元组
  • 10. Python的数据类型:字典(Hash)字典是一个用大括号括起来的键值对,字典元素分为两部份,键(key)和值。 字典是python中唯一内置映射数据类型。通过指定的键从字典访问值。 字典的使用: a = {‘a’:’aa’, ‘b’:’bb’} a[‘c’]=‘cc’ a.has_key(‘a’)
  • 11. Python的数据类型:字典(常用方法)字典的常用方法(演示): has_key(x) keys() values() items() clear() copy() update(x) get(x[,y])
  • 12. Python 控制语句 ifPython支持三种不同的控制结构:if,for和while,不支持C语言中的switch语句。 (1)if 语句的用法: if EXPRESSION1: STATEMENT1 elif EXPRESSION2: STATEMENT2 else: STATEMENT3
  • 13. Python 控制语句 forfor语句的用法: mylist = "for statement" for word in mylist: print word else: #最终执行 print "End list"
  • 14. Python 控制语句 whilewhile语句的用法: a = 0 while a > 5: a = a + 1 print a else: print "a's value is five"
  • 15. Python 循环中的控制语句break: 终止当前循环 continue: 终止本次循环 pass: 什么事都不错
  • 16. Python 函数函数定义: def function_name(arg1,arg2[,...]): statement [return value] 函数名: 函数名必须以下划线或字母开头,可以包含任意字母、数字或下划线的组合。不能使用任何的标点符号; 函数名是区分大小写的。 函数名不能是保留字。
  • 17. Python 函数作用域Python使用名称空间的概念存储对象,这个名称空间就是对象作用的区域, 不同对象存在于不同的作用域。 不同对象的作用域规则: 每个模块都有自已的全局作用域。 函数定义的对象属局部作用域,只在函数内有效,不会影响全局作用域中的对象。 赋值对象属局部作用域,除非使用global关键字进行声明。 LGB规则 大多数名字引用在三个作用域中查找:先局部(Local),次之全局(Global),再次之内置(Build-in)。若仍然找不到这个变量名,则引发NameError异常.
  • 18. Python 函数参数函数的参数分类: 默认参数:def function(ARG=VALUE) 元组参数:def function(*ARG) 字典参数:def function(**ARG) 一些规则: 默认值必须在非默认参数之后; 在单个函数定义中,只能使用一个tuple参数(*ARG)和一个字典参数(**ARG)。 tuple参数必须在连接参数和默认参数之后。 字典参数必须在最后定义。
  • 19. 内置特殊函数apply() 函数apply(func [, args [, kwargs ]]) 函数用于当函数参数已经存在于一个元组或字典中,间接地调用函数. args是一个包含将要提供给函数的按位置传递的参数的元组. 如果省略了args,任何参数都不会被传递. kwargs是一个包含关键字参数的字典. foo(3,“x”, name=‘Dave’, id=12345) apply(foo, (3,“x”), { ‘name’: ‘Dave’, ‘id’: 12345 }) lambda操作符 lambda args: expression args是一个用逗号分隔的参数, expressin是一个调用这些参数的表达式
  • 20. map(), zip(), reduce(), 和filter()t = map(func, s ) . 即t[i] = func(s[i]). 需要注意的是, func函数必须有且只有一个参数 >> a = [1, 2, 3, 4, 5, 6] >> b = map(lambda x: 3*x, a) # b = [3, 6, 9, 12, 15, 18] >> t2 = map(func, s1,s2,…,sn) ? >> t3 = map(None, s1,s2,…,sn) ? zipls = zip(s1 , s2 , ..., sn ) :zipls[i ] = (s1[i ], s2[i ], ..., sn[i ]). zip()函数取决于最短序列. reduce(func , s )函数从一个序列收集信息,然后只返回一个值(例如求和,最大值,等). >> b = reduce(sum, [1,2,3,4,]) # b = (((1+2)+3)+4) = 10 filter(func ,s)是个序列过虑器,使用func()函数来过滤s中的元素。 >> c = filter(lambda x: x < 4, [1,2,3,4,]) # c = [1, 2, 3]
  • 21. 列表内涵列表内涵可以代替许多调用map()和filter()函数的操作. 一般形式是: [表达式 for item1 in 序列1 for item2 in 序列2 ... for itemN in 序列N if 条件表达式] s = [] for item1 in sequence1: for item2 in sequence2: ... for itemN in sequenceN: if condition: s.append(expression)
  • 22. Demoimport math a = [-3,5,2,-10,7,8] b = 'abc‘ c = [2*s for s in a] # c = [-6,10,4,-20,14,16] d = [s for s in a if s >= 0] # d = [5,2,7,8] e = [(x,y) for x in a # e = [(5,'a'),(5,'b'),(5,'c'), for y in b # (2,'a'),(2,'b'),(2,'c'), if x > 0] # (7,'a'),(7,'b'),(7,'c'), # (8,'a'),(8,'b'),(8,'c')] f = [(1,2), (3,4), (5,6)] g = [math.sqrt(x*x+y*y) # g = [2.23606, 5.0, 7.81024] for x,y in f] h = reduce(lambda x,y: x+y, # 平方根的和 [math.sqrt(x*x+y*y) for x,y in f])
  • 23. eval(), exec, execfile(),和compile() eval(str [,globals [,locals ]])函数将字符串str当成有效Python表达式来求值,并返回计算结果。 同样地, exec语句将字符串str当成有效Python代码来执行.提供给exec的代码的名称空间和exec语句的名称空间相同. 最后,execfile(filename [,globals [,locals ]])函数可以用来执行一个文件,看下面的例子: >>> eval('3+4') 7 >>> exec 'a=100‘ >>> a 100 >>> execfile(r'c:\test.py') hello,world!
  • 24. eval(),exec,execfile()名字空间默认eval(),exec,execfile()所运行的代码都位于当前的 名字空间中。eval(), exec,和 execfile()函数也可接受 一个或两个可选字典参数作为代码执行的全局名字空 间和局部名字空间 Demo: globals = {'x': 7, 'y': 10, 'birds': ['Parrot', 'Swallow', 'Albatross'] } locals = { } # 将上边的字典作为全局和局部名称空间 a = eval("3*x + 4*y", globals, locals) exec "for b in birds: print b" in globals, locals 注意语法 execfile("foo.py", globals, locals) exec是一个语句(就象print或while), 而eval()和execfile()则是内建函数.
  • 25. compile(str ,filename ,kind )函数compile()将一个字符串编译为字节代码, str是将要被编译的字符串, filename是定义该字符串变量的文件, kind参数指定了代码被编译的类型 'single'指单个语句, 'exec'指多个语句, 'eval'指一个表达式. 返回一个代码对象,该对象也可以被传递给eval()函数和exec语句来执行 预编译, 可以有效提高程序的执行效率
  • 26. 递归Python对递归函数调用的次数作了限制. 函数 sys.getrecursionlimit()返回当前允许的最大递归次数, 而函数sys.setrecursionlimit()可以改变该函数的返回值. 默认的最大递归次数为1000.当一个函数递归次数超过最大递归次数时,就会引发RuntimeError异常.
  • 27. Python 模块模块:可把一个复杂的程序按功能分开,分别存放到不同文件中,使程序更容易维护和管理。 Python中的模块是以.py结尾的Python代码文件。 通过import命令输入,如: import sys(和c中include语句似乎相似) 该import语句共执行三步操作: 创建新的名称空间(namespace),该名称空间中拥有输入模块中定义的所有对象; 执行模块中的代码; 创建该名称空间的变量名。
  • 28. Python 模块import的使用: import ftplib as ftp from ftplib import FTP
  • 29. Python脚本与模块python脚本和模块都是一个以.py结束的文件,那程序是如何判断一个.py文件是作为脚本还是模块呢? 关键是一个名为__name__的变量,如果它的值是__main__,则是作为脚本直接运行,否则是做为模块运行的。 if __name__ == “__main__”: main()
  • 30. Python 包(package)我们可以把几个功能相近的模块组成一个Python包,存放到一个目录结构中,通过输入包的路径来调用对对象。例子: / WebDesign __init__.py design.py draw.py 其中__init__.py是包的初始化文件,可以为空,但是必不可少的。 可以以下列方式引用design模块: import WebDesign.design
  • 31. Python 类简单例子 #!/usr/bin/python #-*- encoding:utf-8 -*- class test: #定义一个test类 desc = "这是一个测试类。" #在类中定义一个属性desc def __init__(self,name1): #对象构造函数,初始化类 self.name1 = name1 def show(self,name2): #在类中定义一个方法show() print "hello world" print 'name1:',self.name1 print 'name2:',name2 调用 obj = test(‘这是传递给name1的值’) #生成test类的实例对象 print obj.desc #调用类中的desc属性 obj.show('这是传递给name2的值') #调用类中的show()方法
  • 32. 面向对象编程(基于对象) class Foo: def __init__(self, a, b): self.a = a self.b = b def show_a(self): print self.a def show_b(self): print self.b __init__ 函数:每次生成类的时候都会执行的, self 指向类对象自身。 记住, 类函数(或者叫做方法) 它的第一个参数 “self” 不要忘记写了 foo_obj = Foo("I'm A", "I'm B") foo_obj.show_a() foo_obj.b = "Hello world!" foo_obj.show_b()
  • 33. 命名规范类的首字母大写, 没有特别原因不要在前面加 “T” 或者 “C” 什么的 函数和变量尽量全小写, 单词间下划线 python命名规范(约定): 类里面 “单下划线” 开始的成员变量叫做保护变量, 意思是只有类对象和子类对象自己能访问到这些变量; 而 "双下划线" 开始的是私有成员, 意思是只有类对象自己能访问, 连子类对象也不能访问到这个数据。
  • 34. 使用私有成员的一个例子 class Fool: def __init__(self): self.__a = None # None 就是什么都没有 def set_a(self, a): self.__a = a def get_a(self): print self.__a fool_obj = Fool() print fool_obj .__a # 哼哼, 等着报错吧, # # 只有 foo "自己" 才可以 "看见" __a fool_obj.set_a("I'm A") print fool_obj.get_a()
  • 35. 闲言碎语 Java:把对象里面的成员保护起来,程序员似乎养成了习惯。 “隐藏实现” ? python 真正 "隐藏实现" 的方法, 就是重定义等号运算符 用直接操作成员变量的方法来做 (用等号代替函数) 真正漂亮、收放自如的程序敢于暴露自己的实现细节, 用最轻量级的方法来做事情 轻量级的方法通常会很巧妙, 但不会很复杂。
  • 36. 继承class Bar(Fool): def __init__(self, a, b, c, d): Fool.__init__(self, a, b) # 调用父类初始化 self.c = c self.d = d def show_c(self): print self.c def show_d(self): print self.d foo_obj.show_a() foo_obj.show_b() foo_obj.show_c() foo_obj.show_d() 多重继承 class MBar(Foo1, Foo2, Foo3, ...): ….
  • 37. 继承 所谓继承就是让新的类, 子类得到父类 (就是那个 Foo) 的成员和功能。 但是最好不要忘记子类也需要一个 __init__ 函数, 把 a、b、c、d 这些成员都创建出来, 或者直接调用父类的 __init__ 函数来完成这件事情, 并且我们通常是这样做的。
  • 38. 简单的网络通信及即时聊天网络编程。不妨做一个即时聊天工具吧, 不过这次的程序很简陋, 只能说是一个网络对讲机罢了。 from SimpleXMLRPCServer import SimpleXMLRPCServer def foo(): return "Hello world!" server = SimpleXMLRPCServer( ("localhost", 8000) ) server.register_function(foo) server.serve_forever() 用 IE 来访问 http://localhost:8000 看看我们得到了什么? 是一个出错页面, 不错, 这表示我们的服务器工作正常, 只是访问的方法不对而已。
  • 39. 客户机程序对应的客户机程序 from xmlrpclib import ServerProxy server = ServerProxy("http://localhost:8000") print server.foo() 服务器返回了 "Hello world!"。这里 localhost 是指本机, 8000 是端口, 我们通常会指定大于 1024 的端口号。 localhost 我们通常会用域名 (机器名) 或 IP 来代替, 而端口号是任意的。 下面, 该传些东西了。比如发送一句话到服务器上去显示出来。
  • 40. 服务端程序 from SimpleXMLRPCServer import SimpleXMLRPCServer def msg(s): print s return True server = SimpleXMLRPCServer( ("localhost", 8000) ) server.register_function(msg) server.serve_forever() 对应的客户机程序: from xmlrpclib import ServerProxy server = ServerProxy("http://localhost:8000") while True: msg = raw_input() server.msg(msg)
  • 41. 开个玩笑, 一个即时通信工具已经写好了。两台机器互相知道 IP 或者机器名, 协商好端口号。然后打开一个服务器、将客户机指向对方的服务器就可以了。 那么怎么将客户端和服务器合并在一起呢? 因为调用 serve_forever() 之后程序就停在那里了, 所以无法再接收用户输入的东西了。
  • 42. 多线程编程 import thread from SimpleXMLRPCServer import SimpleXMLRPCServer from xmlrpclib import ServerProxy def msg(s): print s return True def run_server(): my_server = SimpleXMLRPCServer( ("localhost", 8001) ) my_server.register_function(msg) my_server.serve_forever() def run_client(): your_server = ServerProxy("http://localhost:8002") while True: msg = raw_input() your_server.msg(msg) thread.start_new_thread( run_server, () ) run_client()
  • 43. 第二个差不多, 只是把地址互换 import thread from SimpleXMLRPCServer import SimpleXMLRPCServer from xmlrpclib import ServerProxy def msg(s): print s return True def run_server(): my_server = SimpleXMLRPCServer( ("localhost", 8002) ) my_server.register_function(msg) my_server.serve_forever() def run_client(): your_server = ServerProxy("http://localhost:8001") while True: msg = raw_input() your_server.msg(msg) thread.start_new_thread( run_server, () ) run_client()
  • 44. 这样, 一对对讲机就写好了图形界面: 用 Tkinter 来写一个界面了。 首先把窗体画出来。 from Tkinter import * wnd = Tk() wnd.lab = Label(wnd, text="---") wnd.ent = Entry(wnd) wnd.btn = Button(wnd, text="send") wnd.lab.pack() wnd.ent.pack(side=LEFT) wnd.btn.pack(side=LEFT) 然后把刚才的网络部分加上去。
  • 45. import thread from SimpleXMLRPCServer import SimpleXMLRPCServer from xmlrpclib import ServerProxy # 第一个对讲机 my_server = SimpleXMLRPCServer( ("localhost", 8002) ) your_server = ServerProxy("http://localhost:8001") # 第二个对讲机 (需要交换一下地址) # my_server = SimpleXMLRPCServer( ("localhost", 8001) ) # your_server = ServerProxy("http://localhost:8002") def msg(s): wnd.lab.config(text=s) return True def run_server(): my_server.register_function(msg) my_server.serve_forever() def send(): msg = wnd.ent.get() wnd.ent.select_range(0, len(msg)) your_server.msg(msg) wnd.btn.config(command=send) thread.start_new_thread( run_server, () ) wnd.mainloop()
  • 46. 程序比较长, 所以另外一个终端就不写了 注意, 这里两台终端的地址是在程序中写死的。而且现在的程序只能显示最近收到的一条消息。 使用 Tkinter 中的输入框来叫用户自己输入目标机器的地址和端口。 使用 Tkinter 中的编辑框组件来显示多行消息。