反射:
把字符串映动态射成对象内存地址。
hasattr():判断一个对象里是否有对应的字符串的方法
getattr():根据字符串去获取obj对象里的对应方法的内存地址。
class Dog(object): def __init__(self,name): self.name = name def eat(self): print('%s is eating...',self.name) d = Dog('NiuHanYang') choice = input('>>:').strip() # choice是字符串,不能直接调用,使用反射 print(hasattr(d,choice))
print(getattr(d,choice)) # 得到的内存地址
getattr(d,choice)() # 调用eat方法
if hasattr(d,choice):
func = getattr(d,choice)
func('chenRonghua')
setattr(): is equivalent to 'x.y =v'
def bulk(self): print('%s is yelling...' %self.name) class Dog(object): def __init__(self,name): self.name = name def eat(self,food): print('%s is eating...'%self.name,food) d=Dog('NiuHanYang') choice = input('>>:').strip() if hasattr(d,choice): func = getattr(d,choice) func('chenRonghua') else: setattr(d,choice,bulk) d.talk(d) >>:talk NiuHanYang is yelling...
动态装方法:
def bulk(self): print('%s is yelling...' %self.name) class Dog(object): def __init__(self,name): self.name = name def eat(self,food): print('%s is eating...'%self.name,food) d=Dog('NiuHanYang') choice = input('>>:').strip() if hasattr(d,choice): func = getattr(d,choice) func('chenRonghua') else: # setattr(d,choice,bulk) # d.talk(d) setattr(d,choice,22) print(getattr(d,choice)) >>:ff 22
delattr(对象,名字):直接名字对象。
class Foo(object): def __init__(self): self.name = 'wupeiqi' def func(self): return 'func' obj = Foo() print(hasattr(obj,'name')) print(hasattr(obj,'func')) print(getattr(obj,'name')) print(getattr(obj,'func')) print(setattr(obj,'age',18)) print(setattr(obj,'show',lambda num:num+1)) # #### 删除成员 #### delattr(obj, 'name') delattr(obj, 'func')
详细解析:
当我们要访问一个对象的成员时,应该是这样操作:
class Foo(object): def __init__(self): self.name = 'alex' def func(self): return 'func' obj = Foo() # 访问字段 obj.name # 执行方法 obj.func()
那么问题来了?
a、上述访问对象成员的 name 和 func 是什么?
答:是变量名
b、obj.xxx 是什么意思?
答:obj.xxx 表示去obj中或类中寻找变量名 xxx,并获取对应内存地址中的内容。
c、需求:请使用其他方式获取obj对象中的name变量指向内存中的值 “alex”
lass Foo(object): def __init__(self): self.name = 'alex' # 不允许使用 obj.name obj = Foo()
答:有两种方式,如下:
class Foo(object): def __init__(self): self.name = 'alex' def func(self): return 'func' # 不允许使用 obj.name obj = Foo() print obj.__dict__['name']
class Foo(object): def __init__(self): self.name = 'alex' def func(self): return 'func' # 不允许使用 obj.name obj = Foo() print getattr(obj, 'name')
d、比较三种访问方式
- obj.name
- obj.__dict__['name']
- getattr(obj, 'name')
答:第一种和其他种比,...
第二种和第三种比,...
#!/usr/bin/env python #coding:utf-8 from wsgiref.simple_server import make_server class Handler(object): def index(self): return 'index' def news(self): return 'news' def RunServer(environ, start_response): start_response('200 OK', [('Content-Type', 'text/html')]) url = environ['PATH_INFO'] temp = url.split('/')[1] obj = Handler() is_exist = hasattr(obj, temp) if is_exist: func = getattr(obj, temp) ret = func() return ret else: return '404 not found' if __name__ == '__main__': httpd = make_server('', 8001, RunServer) print "Serving HTTP on port 8000..." httpd.serve_forever()
结论:反射是通过字符串的形式操作对象相关的成员。一切事物都是对象!!!
设计模式:
一、单例模式
单例,顾名思义单个实例。
学习单例之前,首先来回顾下面向对象的内容: python的面向对象由两个非常重要的两个“东西”组成:类、实例 面向对象场景一: 如:创建三个游戏人物,分别是: 苍井井,女,18,初始战斗力1000 东尼木木,男,20,初始战斗力1800 波多多,女,19,初始战斗力2500
# ##################### 定义类 ##################### class Person: def __init__(self, na, gen, age, fig): self.name = na self.gender = gen self.age = age self.fight =fig def grassland(self): """注释:草丛战斗,消耗200战斗力""" self.fight = self.fight - 200 # ##################### 创建实例 ##################### cang = Person('苍井井', '女', 18, 1000) # 创建苍井井角色 dong = Person('东尼木木', '男', 20, 1800) # 创建东尼木木角色 bo = Person('波多多', '女', 19, 2500) # 创建波多多角色
面向对象场景二:
如:创建对数据库操作的公共类
- 增
- 删
- 改
- 查
# #### 定义类 #### class DbHelper(object): def __init__(self): self.hostname = '1.1.1.1' self.port = 3306 self.password = 'pwd' self.username = 'root' def fetch(self): # 连接数据库 # 拼接sql语句 # 操作 pass def create(self): # 连接数据库 # 拼接sql语句 # 操作 pass def remove(self): # 连接数据库 # 拼接sql语句 # 操作 pass def modify(self): # 连接数据库 # 拼接sql语句 # 操作 pass # #### 操作类 #### db = DbHelper() db.create()
实例:结合场景二实现Web应用程序
#!/usr/bin/env python #coding:utf-8 from wsgiref.simple_server import make_server class DbHelper(object): def __init__(self): self.hostname = '1.1.1.1' self.port = 3306 self.password = 'pwd' self.username = 'root' def fetch(self): # 连接数据库 # 拼接sql语句 # 操作 return 'fetch' def create(self): # 连接数据库 # 拼接sql语句 # 操作 return 'create' def remove(self): # 连接数据库 # 拼接sql语句 # 操作 return 'remove' def modify(self): # 连接数据库 # 拼接sql语句 # 操作 return 'modify' class Handler(object): def index(self): # 创建对象 db = DbHelper() db.fetch() return 'index' def news(self): return 'news' def RunServer(environ, start_response): start_response('200 OK', [('Content-Type', 'text/html')]) url = environ['PATH_INFO'] temp = url.split('/')[1] obj = Handler() is_exist = hasattr(obj, temp) if is_exist: func = getattr(obj, temp) ret = func() return ret else: return '404 not found' if __name__ == '__main__': httpd = make_server('', 8001, RunServer) print "Serving HTTP on port 8001..." httpd.serve_forever()
对于上述实例,每个请求到来,都需要在内存里创建一个实例,再通过该实例执行指定的方法。
那么问题来了...如果并发量大的话,内存里就会存在非常多功能上一模一样的对象。存在这些对象肯定会消耗内存,对于这些功能相同的对象可以在内存中仅创建一个,需要时都去调用,也是极好的!!!
铛铛 铛铛 铛铛铛铛铛,单例模式出马,单例模式用来保证内存中仅存在一个实例!!!
通过面向对象的特性,构造出单例模式:
# ########### 单例类定义 ########### class Foo(object): __instance = None @staticmethod def singleton(): if Foo.__instance: return Foo.__instance else: Foo.__instance = Foo() return Foo.__instance # ########### 获取实例 ########### obj = Foo.singleton()
对于Python单例模式,创建对象时不能再直接使用:obj = Foo(),而应该调用特殊的方法:obj = Foo.singleton() 。
#!/usr/bin/env python #coding:utf-8 from wsgiref.simple_server import make_server # ########### 单例类定义 ########### class DbHelper(object): __instance = None def __init__(self): self.hostname = '1.1.1.1' self.port = 3306 self.password = 'pwd' self.username = 'root' @staticmethod def singleton(): if DbHelper.__instance: return DbHelper.__instance else: DbHelper.__instance = DbHelper() return DbHelper.__instance def fetch(self): # 连接数据库 # 拼接sql语句 # 操作 pass def create(self): # 连接数据库 # 拼接sql语句 # 操作 pass def remove(self): # 连接数据库 # 拼接sql语句 # 操作 pass def modify(self): # 连接数据库 # 拼接sql语句 # 操作 pass class Handler(object): def index(self): obj = DbHelper.singleton() print id(single) obj.create() return 'index' def news(self): return 'news' def RunServer(environ, start_response): start_response('200 OK', [('Content-Type', 'text/html')]) url = environ['PATH_INFO'] temp = url.split('/')[1] obj = Handler() is_exist = hasattr(obj, temp) if is_exist: func = getattr(obj, temp) ret = func() return ret else: return '404 not found' if __name__ == '__main__': httpd = make_server('', 8001, RunServer) print "Serving HTTP on port 8001..." httpd.serve_forever()
总结:单利模式存在的目的是保证当前内存中仅存在单个实例,避免内存浪费!!!
动态导入模块:
__import__('import_lib.metaclass‘)#这是解释器自己内部用的
mod = __import__('lib.aa')
print(mod.aa)
obj=mod.aa.C()
print(obj.name)
import importlib __import__('import_lib.metaclass') #这是解释器自己内部用的 #importlib.import_module('import_lib.metaclass') #与上面这句效果一样,官方建议用这个
mod = __import__('lib.aa') print(mod.aa) obj=mod.aa.C() print(obj.name) /usr/bin/python3.5 /home/ld/mytest/day3/test_dimport.py crh