Python开发Day07
生成器
介绍:
-
-
在使用少量的内存情况下经行这与使用较多内存的性质一样,就是占用内存量少
-
例如在Python2.*中使用range(1,10)会在内存中直接创建1-9的列表,在Python3.*中range(1,10)他只会在循环时或者__next__时才会起作用
-
使用:
-
-
在使用生成器是我们需要使用函数和yield来实现。例如:
View Codedef a1(n,n2=None): if n2 != None: start = n while True: if start >= n2: return yield start start += 1 else: start = 0 while True: if start >= n: return yield start start += 1 for i in a1(2): print(i) 执行结果: 0 1
或:
View Codedef a1(n,n2=None): if n2 != None: start = n while True: if start >= n2: return yield start start += 1 else: start = 0 while True: if start >= n: return yield start start += 1 aa = a1(2) print(aa.__next__()) print(aa.__next__()) 执行结果: 0 1
-
迭代器
介绍:
-
-
对于Python 列表的 for 循环,他的内部原理:查看下一个元素是否存在,如果存在,则取出,如果不存在,则报异常 StopIteration。(python内部对异常已处理)
-
使用:
-
-
利用for循环就是。
-
反射
介绍:
-
-
根据字符串的形式,去对象(或模块)中操作其成员。
-
反射是通过字符串的形式操作对象相关的成员。
-
使用:
-
-
getattr方法:
View Codeimport test#导入自定义模块test a = input('请输入')#自定义输入内容 ac = getattr(test,a)#使用模块test下的a方法 ac()#执行a方法 执行结果: 请输入login 登陆成功!
-
hasattr方法:
View Codeimport test#导入自定义模块test a = input('请输入')#自定义输入内容 ac = hasattr(test,a)#判断模块test下有没有用户输入的a方法 print(ac)#输出结果True为有用户输入的方法,False为没有 执行结果: 请输入login True
-
setattr方法:
View Codeimport test#导入自定义模块test setattr(test,'age','hello')#在test模块下设置一个变量为age值为hello ac = getattr(test,'age')#将test模块下的age变量给ac print(ac)#查看ac的值 执行结果: hello
-
delattr方法:
View Codeimport test#导入自定义模块test a = hasattr(test,'login')#判断test模块下有没有login方法 print(a)#输出True或Flase delattr(test,'login')#删除login方法 a = hasattr(test,'login')#判断test模块下有没有login方法 print(a)#输出True或Flase 执行结果: True False
-
test模块内容:
View Code#!/usr/bin/python # -*- coding: utf-8 -*- __author__ = 'WuYongQi' def login(): print('登陆成功!') return 'Yes' def logout(): print('退出成功!') return 'No' def Nb(): print('太牛逼了') return 'NB'
-
综合调用:
View Codeurl = input('请输入网站:')#用户输入网站以字符串的形式保存,例如(test/login) inp_modul,inp_user = url.split('/')#将用户输入的url以/分割,(['test','login']) modul = __import__(inp_modul,fromlist=True)#使用__import__以字符串的形式导入模块,(导入test,并且支持路径的拼接) if hasattr(modul,inp_user):#判断用户输入的模块名和函数是否存在 a = getattr(modul,inp_user)#用户输入的存在执行getattr将函数赋值给变量a a()#执行a函数 else:#否则函数不存在报404 print('404') 执行结果: 请输入网站:test/login 登陆成功!
-
面向对象
介绍:
-
-
面向对象是:对函数进行分类和封装,让开发“更快更好更强...”
-
面向过程是:根据业务逻辑从上到下写垒代码、
-
函数式编程是:将某功能代码封装到函数中,日后便无需重复编写,仅调用函数即可
-
面向对象编程不是所有地方都适用的,因为有些时候函数式编程会比面向对象代码量更少更好。
-
如果你写了一个函数需要传很多次参数就可以使用面向对象
-
如果写了一个函数,各个函数之间是独立且无共用的数据,推荐使用函数式编程
-
-
使用:
-
-
创建一个类:
class hhha: #class为关键字,hhha为类名称 def test(self): print('hello') obj = hhha() #调用hhha类 obj.test() #执行hhha类中的test方法
-
面向对象的三大特新:
-
封装:就是将内容封装到某个地方,以后需要时去被封装的地方调用需要的内容。
-
在使用面向对象封装的时候我们需要
-
将内容封装到某处
View Codeclass test:#创建一个test类 def __init__(self,name,age): #self为特殊参数必须填写(在执行类的时候会给类附一个对象self就是那个对象的意思) self.name=name self.age=age a = test('Wu',20)#将Wu和20封装到a的self.name和self.age属性中
封装后的对象是独立出现的,例如内存中有一个obj1=test('Wu','20'),一个obj2=test('Yong','21'),那么在内存他们各自有各自的内存地址并且存储的内容也不同
- 从某处调用被封装的内容
- 调用被封装的内容时,有两种情况:
- 通过对象直接调用
View Codeclass test: def __init__(self,name,age): self.name = name self.age = age def hello(self): print(self.name,self.age) a = test('WuYongqi',21) print(a.name) print(a.age) 执行结果: WuYongqi 21
- 通过self间接调用
View Codeclass test: def __init__(self,name,age): self.name = name self.age = age def hello(self): print('%s \n%s'%(self.name,self.age)) a = test('WuYongqi',21) a.hello()# Python默认会将a传给self参数,即:a.hello(a),所以,此时方法内部的 self = a,即:self.name 是 WuYongqi;self.age 是 20 执行结果: WuYongqi 21
- 通过对象直接调用
- 调用被封装的内容时,有两种情况:
- 使用封装写一个模拟人生:
View Codeclass monirensheng: def __init__(self,name,genter,jingyan=0): self.name=name self.genter=genter self.jingyan=jingyan def xiulian(self): self.jingyan += 100 print('%s 获得经验100'%self.name) print('%s 当前经验为 %d'%(self.name,self.jingyan)) print('__________________________________________________________') def daBOSS(self): self.jingyan += 1500 print('%s 获得经验1500'%self.name) print('%s 当前经验为 %d'%(self.name,self.jingyan)) print('__________________________________________________________') def jiehun(self): self.jingyan += 1000 print('%s 因结婚系统奖励1000经验'%self.name) print('%s 当前经验为 %d'%(self.name,self.jingyan)) print('__________________________________________________________') import pickle a=pickle.load(open('db.log','rb')) #a=monirensheng('Wu','man',) while True: print("1.打BOSS\n2.修炼\n3.退出") ab=input('').strip() if ab: if ab.isdigit(): if int(ab) == 1: a.daBOSS() elif int(ab) == 2: a.xiulian() elif int(ab) == 3: break else: print('输入有误!') else: print('输入有误!') else: print('输入有误!') pickle.dump(a,open('db.log','wb'))
利用了pickle
-
-
-
继承:面向对象中的继承就犹如现实生活中的儿子可以继承父亲的关系。
- 写一个关于猫狗的继承关系,因为猫狗同属于动物,吃喝拉撒为一个类,自己的特性为一个类
View Codeclass Animal:#父类也称为基类 def eat(self): print("%s 吃 " %self.name) def drink(self): print("%s 喝 " %self.name) def shit(self): print("%s 拉 " %self.name) def pee(self): print("%s 撒 " %self.name) class Cat(Animal):#子类称之为派生类 def __init__(self, name): self.name = name def cry(self): print('喵~~~~') class Dog(Animal):#子类称之为派生类 def __init__(self, name ): self.name = name def cry(self): print('汪~~~') c1 = Cat('猫') c1.eat() c2 = Cat('猫') c2.drink() d1 = Dog('狗') d1.eat() 执行结果: 猫 吃 猫 喝 狗 吃
- 多继承:在Python中一个子类可以继承多个父类,但是他们之间的关系是怎么样的呢?
View Codeclass A: def f1(self): print('A') class B(A): def f1(self): print('B') class C(A): def f1(self): print('C') class D: def f1(self): print('D') class E: def f1(self): print('E') class F(D,E): def f1(self): print('F') abc = F() abc.f1() 执行结果: F
多继承关系图

- 写一个关于猫狗的继承关系,因为猫狗同属于动物,吃喝拉撒为一个类,自己的特性为一个类
-
多态
- Pyhon是不支持多态的并且也用不到多态,多态的概念是应用于Java和C#这一类强类型语言中,而Python崇尚的是“鸭子类型”。
View Codeclass F1: pass class S1(F1): def show(self): print 'S1.show' class S2(F1): def show(self): print 'S2.show' def Func(obj): print obj.show() s1_obj = S1() Func(s1_obj) s2_obj = S2() Func(s2_obj)
多态不需要知道太深,了解一下就可以!
- Pyhon是不支持多态的并且也用不到多态,多态的概念是应用于Java和C#这一类强类型语言中,而Python崇尚的是“鸭子类型”。
-
一张图片介绍类和对象在内存中是如何保存的:
-
-

-
-
一个类是用什么创建的?
-
在Python中一切事物皆是对象
-
类生成对象,创建类使用的是type
-
-
面向对象进阶:
-
成员:
-
字段:
- 静态字段:每个对象都有一份的时候
- 在class下直接使用变量的形式来创建字段
- 静态字段在类中的话可以使用类名.静态字段名。(自己去访问自己的成员)
- 自己去访问自己的成员除了类中的方法不要让对象去访问
- 普通字段:每个对象都是不同数据的时候
- 静态字段:每个对象都有一份的时候
-
方法:
View Codeclass ttt: country = '中国' # 静态字段 def __init__(self,name):#构建 self.name = name temp = 'Hello' #普通方法,对象中 #静态方法 @staticmethod def hello(a,c): print(a,c) #普通方法 def show(self): print(self.name) @classmethod def word(cls): print('hello word\t\t\t%s'%cls) ttt.word() ttt.hello(111,222) print(ttt.country) 执行结果: hello word <class '__main__.ttt'> 111 222 中国
- 静态方法:不使用对象封装的内容的时候(由类调用)
- @statcmetchod将类中的某一个方法转换成静态方法
- 类方法:需要当前这个类的时候使用。(由类调用)
- @classmetchod将类中的方法转成类的方法。
- 必须要有一个cls参数
- 执行:类名称.方法名()
- 普通方法:要使用对象中数据的时候。(由对象调用)
- 静态方法:不使用对象封装的内容的时候(由类调用)
-
特性:
View Codeclass test: def __init__(self,name): self.name = name def hello(self): ab = self.name return ab @property def hello2(self): a=self.name+'123' return a @hello2.setter def hello2(self,name): print(name) self.name = name ab = test('alex') a1=ab.hello() a2=ab.hello2 print(a1,a2) ab.hello2 = '????'#设置属性 a1=ab.hello() a2=ab.hello2 print(a1,a2) 执行结果: alex alex123 ???? ???? ????123
- 普通特性:为了把方法伪装成字段的形式来访问
- @property将类中原来的方法伪装成字段的方法去获取
- @end.setter设置对应特性方法的值
- 在使用特性后的方法不可以添加参数了
- 普通特性:为了把方法伪装成字段的形式来访问
-
判断是使用类还是对象执行:
- 在使用特性后的方法不可以添加参数了
- 有self,对象调用
-
-
成员修饰符:
View Codeclass tst: __ab = '123a' ac = 'nihao' def __init__(self): self.__name= '???我' def hello(self): print(self.__name) obj = tst() print(obj._tst__name) 执行结果: ???我
-
每一个类的成员都有两种形式
- 共有成员:在任何地方都可以访问使用的。(类、类的内部、派生类)
- 私有成员:只能在类的内部使用和访问。(类的内部)
- 如果想要强制访问私有字段,可以通过 对象名._类名__私有字段明 来访问(如:obj._C__foo),不建议强制访问私有成员。
-
私有成员和共有成员的定义
- 私有成员命名时,前两个字符是下划线。(特殊成员除外,例如:__init__、__call__、__dict__等)
- 公共成员及正常定义
-
-
面向对象中一些常用的特殊成员:
View Codeclass Foo: ''' 类的注释 ''' def __init__(self): print('init') def __call__(self, *args, **kwargs): print('hello') return 1 def __delitem__(self, key): print(key) def __getitem__(self, item): print(item) def __setitem__(self, key, value): print(key,value) def __iter__(self): yield 1 yield 2 yield 4 yield 2 print(Foo()()) ab = Foo() #__call__ ab['hello'] #__getitem ab['hello'] = 'word' #setitem del ab['asdvnadksga'] #delitem ab[1:5] #getitem ab[1:5] = [11,22,33,44] #setitem del ab[1:2] #delitem print(ab.__dict__) print(Foo.__dict__) for i in ab: print(i) 执行结果: init hello 1 init hello hello word asdvnadksga slice(1, 5, None) slice(1, 5, None) [11, 22, 33, 44] slice(1, 2, None) {} {'__setitem__': <function Foo.__setitem__ at 0x000001D37C3872F0>, '__getitem__': <function Foo.__getitem__ at 0x000001D37C387268>, '__module__': '__main__', '__init__': <function Foo.__init__ at 0x000001D37C3870D0>, '__weakref__': <attribute '__weakref__' of 'Foo' objects>, '__doc__': '\n 类的注释\n ', '__dict__': <attribute '__dict__' of 'Foo' objects>, '__iter__': <function Foo.__iter__ at 0x000001D37C387378>, '__delitem__': <function Foo.__delitem__ at 0x000001D37C3871E0>, '__call__': <function Foo.__call__ at 0x000001D37C387158>} 1 2 4 2
-
__doc__ :表示类的描述信息。
-
__getitem__ :在对象后跟[]默认执行getitem方法
-
__setitem__ :在对象后跟[]= 值 默认执行__setitem__
-
__delitem__ :del[值] 默认执行__delitem__
-
__getslice__ :在Python2.*列表分割使用该方法,在Python3.*之后就是getitem
-
__module__ :表示当前操作的对象在那个模块。
-
__class__ :表示当前操作的对象的类是什么。
-
__init__ :构造方法,通过类创建对象时,自动触发执行。
-
__del__ :析构,解释器销毁对象的时候自动调用。
-
__dict__ :查看类或对象中的所有成员。
-
__call__ :对象后面加括号,触发执行。(构造方法的执行是由创建对象触发的,即:对象 = 类名() ;而对于 __call__ 方法的执行是由对象后加括号触发的,即:对象() 或者 类()())
-
__iter__ :迭代器
-
__srt__ :使用print对象的时候默认执行__str__方法
-
异常处理
-
介绍:
-
在编程过程中为了增加友好性,在程序出现bug时一般不会将错误信息显示给用户,而是现实一个提示的页面,通俗来说就是不让用户看见大黄页!!!
-
-
使用:
-
让用户输入一个数字并且转换成int类型,如果用户输入的是字符串则会报错:
inp = input('请输入') try: a = int(inp) except Exception as e: print(e) 执行结果: 请输入s invalid literal for int() with base 10: 's'
-
我们一些常见的异常:
View CodeAttributeError 试图访问一个对象没有的树形,比如foo.x,但是foo没有属性x IOError 输入/输出异常;基本上是无法打开文件 ImportError 无法引入模块或包;基本上是路径问题或名称错误 IndentationError 语法错误(的子类) ;代码没有正确对齐 IndexError 下标索引超出序列边界,比如当x只有三个元素,却试图访问x[5] KeyError 试图访问字典里不存在的键 KeyboardInterrupt Ctrl+C被按下 NameError 使用一个还未被赋予对象的变量 SyntaxError Python代码非法,代码不能编译(个人认为这是语法错误,写错了) TypeError 传入对象类型与要求的不符合 UnboundLocalError 试图访问一个还未被设置的局部变量,基本上是由于另有一个同名的全局变量, 导致你以为正在访问它 ValueError 传入一个调用者不期望的值,即使值的类型是正确的
-
其他的异常
View CodeArithmeticError AssertionError AttributeError BaseException BufferError BytesWarning DeprecationWarning EnvironmentError EOFError Exception FloatingPointError FutureWarning GeneratorExit ImportError ImportWarning IndentationError IndexError IOError KeyboardInterrupt KeyError LookupError MemoryError NameError NotImplementedError OSError OverflowError PendingDeprecationWarning ReferenceError RuntimeError RuntimeWarning StandardError StopIteration SyntaxError SyntaxWarning SystemError SystemExit TabError TypeError UnboundLocalError UnicodeDecodeError UnicodeEncodeError UnicodeError UnicodeTranslateError UnicodeWarning UserWarning ValueError Warning ZeroDivisionError -
捕捉异常(IndexError):
View Codea = [11,22,33,44] try: print(a[5]) except IndexError as e: print(e) 执行结果: list index out of range
这样的定义如果说出现一个错误不是IndexError异常那么就不会捕捉:
View Codea = [11,22,33,44] try: print(a['asd']) except IndexError as e: print(e) 执行结果: Traceback (most recent call last): File "F:/oldboy-Python/py_code/test/day06/class_next/test123.py", line 165, in <module> print(a['asd']) TypeError: list indices must be integers or slices, not str
-
从上述中我们可以看出来捕捉异常只能捕捉一个,那么想捕捉多个怎么办?
View Codeimp = 'asdfds' try: num = int(imp) print(num) except ValueError:#捕捉ValueError错误 print('数据类型转换失败!') except TypeError as a:#捕捉TypeError错误 print(a) except Exception as e:#捕捉所有出现的错误 print('出现位置错误式发发送给管理员') 执行结果: 数据类型转换失败!
-
异常的其他结构:
View Codetry: # 主代码块 except KeyError,e: # KeyError错误 # 异常时,执行该块 pass else: # 主代码块执行完,执行该块 pass finally: # 无论异常与否,最终执行该块 pass
-
我们设置一个主动触发的异常,就是说本来没有错但是我们希望他报错:
View Codetry: num = int(imp) print(num) raise TypeError('出现问题,请联系管理员进行处理!') except ValueError:#捕捉ValueError错误 print('数据类型转换失败!') except TypeError as a:#捕捉TypeError错误 print(a) except Exception as e:#捕捉所有出现的错误 print('出现位置错误式发发送给管理员') 执行结果: 请输入1 1 出现问题,请联系管理员进行处理!
-
断言:
- 差不多和判断一样如判断通过则通过,不通过直接触发错误
View Codeimp = 1 try: assert imp == 2 print(imp) raise TypeError('出现问题,请联系管理员进行处理!') except ValueError:#捕捉ValueError错误 print('数据类型转换失败!') except TypeError as a:#捕捉TypeError错误 print(a) except Exception as e:#捕捉所有出现的错误 print('出现位置错误以发送给管理员') 执行结果: 出现位置错误以发送给管理员
- 差不多和判断一样如判断通过则通过,不通过直接触发错误
-
单例模式
-
介绍:
-
单例,顾名思义单个实例。
-
假如说是我们做了一个服务端,当用户来访问的时候执行一个类(这个类的值是固定不变的),那么如果有一万个用户来访问这个类就执行一万次,这样的话有些浪费内存所以当值是固定的时候最好使用单列模式
-
-
使用:
-
单例模式就是用来保证内存中仅存在一个实例!!!
View Codeclass Foo(object):#创建一个类 __instance = None # 定义一个私有成员值为None @staticmethod def singleton(): # 定义一个静态方法 if Foo.__instance: # 判断类中的私有成员值是不是成立,None是不成立的 return Foo.__instance # 如果成立就把这个类的对象返回 else: #判断类中的私有成员是不成立的 Foo.__instance = Foo() # 将类中的私有成员定义成对象 return Foo.__instance #返回这个类的对象返回 obj = Foo.singleton() # 将Foo类创建一个对象为obj,并执行类中的singleton方法
-
使用网页来做一个单例模式
View Codefrom wsgiref.simple_server import make_server class ConnectionPool: __instance = None def __init__(self): self.ip = "1.1.1.1" self.port = 3306 self.pwd = "123123" self.username = 'xxxx' # 去连接 self.conn_list = [1,2,3,4,5,6,7,8,9, 10] @staticmethod def get_instance(): if ConnectionPool.__instance: return ConnectionPool.__instance else: # 创建一个对象,并将对象赋值给静态字段 __instance ConnectionPool.__instance = ConnectionPool() return ConnectionPool.__instance def get_connection(self): # 获取连接 import random r = random.randrange(1,11) return r def index(): # p = ConnectionPool() # print(p) p = ConnectionPool.get_instance() conn = p.get_connection() return "conn" + str(conn) def news(): return 'new' def RunServer(environ, start_response): start_response(status='200 OK', headers=[('Content-Type', 'text/html')]) url = environ['PATH_INFO'] if url.endswith('index'): ret = index() return ret elif url.endswith('news'): ret = news() return ret else: return ' 404 ' if __name__ == '__main__': httpd = make_server('', 8080, RunServer) print("Serving HTTP on port 8008...") httpd.serve_forever() 使用Python2.7执行,3.*有些问题,执行后使用浏览器访问127.0.0.1:8080或者127.0.0.1:8080/index或者127.0.0.1:8080/news或者127.0.0.1:8080/任何
-
学生选课练习题!要求:
选课系统 管理员: 创建老师:姓名、性别、年龄、资产 创建课程:课程名称、上课时间、课时费、关联老师 使用pickle保存在文件 学生: 学生:用户名、密码、性别、年龄、选课列表[]、上课记录{课程1:【di,a,】} 1、列举所有课程 2、选择课程 3、学生上课, 4、ret = 课程.work() 获取课程的返回; 资产+=课时费

浙公网安备 33010602011771号