day29 二十九、元类、单例
一、eval、exec内置函数
1、eval函数
eval内置函数的使用场景:
①执行字符串会得到相应的执行结果
②一般用于类型转换得到dict、list、tuple等
2、exec函数
exec应用场景 用来辅助了解元类的概念
①执行字符串没有执行结果(没有返回值)
②将执行的字符串中产生的名字形成对应的局部名称空间
解析exec函数
exec函数帮我们运行字符串中的代码,把字符串中产生的名字放到名称空间里 自己定义全局作用域中的名字和字典,自己定义局部作用域的名字和字典
将所要执行的代码放到字符串中,在字符串中写好操作全局作用域的和局部作用域的 字符串内放一堆代码,exec来运行字符串中的代码的时候产生的名字都会放到名称空间里,
放到自己定义的全局或者是局部的名称空间里,如果声明是global,就会放到global的字典里
exec(字符串,global_dic, local_dic)
code = """
global x
x=0
y=2
"""
global_dic = {'x': 100000}
local_dic = {}
exec(code, global_dic, local_dic)
print(global_dic)
print(local_dic) # {'y': 2} code = """
x=1
y=2
def f1(self,a,b):
pass
"""
local_dic = {}
exec(code, {}, local_dic)
print(local_dic) # {'x': 1, 'y': 2, 'f1': <function f1 at 0x00000000027A8C80>}
二、类的名称空间的控制
class A:
pass print(A.__dict__) a = A()
print(a, type(a)) # <__main__.A object at 0x00000000021E7400> <class '__main__.A'> print(A, type(A)) # <class '__main__.A'> <class 'type'> print(type) # <class 'type'>
print(type(type)) # <class 'type'> python中万物皆对象,所有用来创建对象的类,本身也是对象,类是type类的对象
type类叫做元类,是所有元类的基类
元类:制造类的类 --类的类
控制类的产生
控制类的对象的产生 s = '''
my_a = 10
my_b = 20
def __init__(self):
pass
@classmethod
def print_msg(cls, msg):
print(msg)
'''
dic = {}
exec(s, {}, dic) C = type('C', (object, ), dic)
print(C, type(C), C.__bases__) # <class '__main__.C'> <class 'type'> (<class 'object'>,)
print(C.__dict__)
c1 = C()
print(c1.my_a) #
C.print_msg('') class D:
my_a = 10
my_b = 20 def __init__(self):
pass
@classmethod
def print_msg(cls, msg):
print(msg) c1 = C()
print(c1.my_a) #
C.print_msg('') #
三、元类
1、定义:
python中万物皆对象,所有用来创建对象的类,本身也是对象,类是type类的对象
type类叫做元类,是所有元类的基类
元类:制造类的类 --类的类
控制类的产生
控制类的对象的产生
2、__init__、__call__、__new__的用法
①__init__:实例化的时候会自动触发__init__的执行
②__call__:调用类的时候会自动触发
class Zoo:
def __init__(self):
print('') # 对象实例化时候触发
def __str__(self): # 打印对象的时候产生
return 'abc'
def __del__(self): # 删除对象的时候触发
pass
def __call__(self, *args, **kwargs): # 调用类的时候触发
print('')
obj = Zoo() #
print(obj) # abc
obj() # 2 # 调用对象
③__new__:
class CountError(Exception):
pass class MyMeta(type): # 自定义元类,重写init方法的目的:
# 1.该方法是从type中继承来的,所以参数同type的init
# 2.最终的工作(如果开辟空间,如果操作内存)还是要借助type
# 3.在交给type最终完成工作之前,可以对类的创建加以限制 *****
def __init__(cls, class_name: str, bases, namespace):
print(cls) # <class '__main__.Student'>
print(class_name) # Student
print(bases) # (<class 'object'>,)
print(namespace) # {'__module__': '__main__', '__qualname__': 'Student', '__init__': <function Student.__init__ at 0x0000000001EA89D8>}
# 需求:由给元类控制的类的类名必须首字母大写
if not class_name.istitle():
raise NameError('名字首字母必须大写')
# 需求:定义类是必须明确父类
if len(bases) == 0:
raise CountError('父类必须明确') # super(MyMeta, cls).__init__(class_name, bases, namespace)
super().__init__(class_name, bases, namespace) # 自定义元类,重写call方法的目的:
# 1.被该元类控制的类生成对象,会调用元类的call方法
# 2.在call中的返回值就是创建的对象
# 3.在call中
# 通过object开辟空间产生对象
# 用被控制的类回调到自己的init方法完成名称空间的赋值
# 将修饰好的对象反馈给外界
def __call__(cls, *args, **kwargs):
print('call fn run') # call fn run
obj = object.__new__(cls)
# 需求:所有通过该元类控制的类产生的对象都有meta_name该属性
obj.meta_name = cls.__name__
# obj.name = args[0]
# 调回当前被控制的类自身的init方法,完成名称空间的赋值
cls.__init__(obj, *args, **kwargs)
return obj # Student = MyMeta(class_name, bases, namespace)
class Student(object, metaclass=MyMeta):
def __init__(self, name, age):
print('init fn run') # init fn run
self.name = name
self.age = age
pass # stu = Student() # class Teacher(Student, metaclass=MyMeta):
# pass stu = Student('Bob', 18)
print(stu, stu.name, stu.age) # <__main__.Student object at 0x0000000001EB7FD0> Bob 18
stu = Student('Tom', 20)
print(stu.meta_name) # Student
3、自定义元类控制类的创建
需求:类名的首字母必须大写;类中必须写好文档注释
①需求:类名首字母必须大写
class Mymeta(type):
def __init__(self, class_name, class_bases, class_dic):
if not class_name.istitle():
raise TypeError('类名必须大写')
super().__init__(class_name, class_bases, class_dic) # 重用父类的方法 class Foo(object, metaclass=Mymeta):
pass ②需求: 类中必须有文档注释
class Mymeta(type):
def __init__(self, class_name, class_bases, class_dic):
if not class_dic.get('__doc__'):
raise TypeError('类中必须写好文档注释')
super().__init__(class_name, class_bases, class_dic) class Zoo(metaclass=Mymeta):
"""
文档注释
"""
pass
四、单例
1、定义:一个类只能产生一个实例
2、为什么要有单例:
①该类需要对象的产生
②对象一旦产生,在任何位置再实例化对象,只能得到第一次实例化出来的对象
3、单例实现的四种方法:
①方法1
class Songs():
__instance = None
@classmethod
def getInstance(cls):
# 对象没有创建返回,有直接返回
if cls.__instance == None:
cls.__instance = cls()
return cls.__instance # 约定别用 类名() 来实例化对象,用类方法来获取唯一对象
s1 = Songs()
s2 = Songs() print(s1) # <__main__.Songs object at 0x0000000001E776D8>
print(s2) # <__main__.Songs object at 0x0000000001E77710>
print(s1 is s2) # False s1 = Songs.getInstance()
s2 = Songs.getInstance() print(s1) # <__main__.Songs object at 0x00000000027A76D8>
print(s2) # <__main__.Songs object at 0x00000000027A76D8>
print(s1 is s2) # True ②方法2
class Songs:
__instance = None
def __new__(cls, song_name, *args, **kwargs):
if cls.__instance == None:
cls.__instance = object.__new__(cls)
cls.__instance.song_name = song_name
return cls.__instance def change_song(self, song_name):
self.song_name = song_name s1 = Songs('菊花爆满山')
s2 = Songs('感觉身体被掏空')
print(s1.song_name, s2.song_name) # 菊花爆满山 菊花爆满山
s2.change_song('感觉身体被掏空')
print(s1.song_name, s2.song_name) # 感觉身体被掏空 感觉身体被掏空 ③方法3:采用装饰器
def outer(cls):
_instance = None
def inner(*args, **kwargs):
nonlocal _instance
if _instance == None:
_instance = cls(*args, **kwargs)
return _instance
return inner @outer # Songs = outer(Songs)
class Songs:
pass s1 = Songs()
s2 = Songs()
print(s1) # <__main__.Songs object at 0x0000000001EB7748>
print(s2) # <__main__.Songs object at 0x0000000001EB7748>
print(s1 is s2) # True ④方法4
class SingleMeta(type):
__instance = None
def __call__(cls, *args, **kwargs):
if SingleMeta.__instance == None:
SingleMeta.__instance = object.__new__(cls)
cls.__init__(SingleMeta.__instance, *args, **kwargs)
return SingleMeta.__instance class Songs(metaclass=SingleMeta):
def __init__(self):
pass
pass s1 = Songs()
s2 = Songs()
print(s1) # <__main__.Songs object at 0x0000000001E775C0>
print(s2) # <__main__.Songs object at 0x0000000001E775C0>
print(s1 is s2) # True
day29 二十九、元类、单例的更多相关文章
- 29 内置方法 eval | exec 元类 单例
eval与exec内置方法 将字符串作为执行目标,得到响应结果 eval常用作类型转换:该函数执行完有返回值 exec拥有执行更复杂的字符串:可以形成名称空间 eval内置函数的使用场景: 1.执 ...
- Java学习笔记(二十四):单例设计模式singleton
为什么要使用singleton设计模式? 假设设计了一个操作数组的工具类(Tools),里面有一个锤子的方法(Hammer),如果不使用singleton设计模式,每次想调用Hammer方法都需要ne ...
- Bootstrap <基础二十九>面板(Panels)
Bootstrap 面板(Panels).面板组件用于把 DOM 组件插入到一个盒子中.创建一个基本的面板,只需要向 <div> 元素添加 class .panel 和 class .pa ...
- mysql进阶(二十九)常用函数
mysql进阶(二十九)常用函数 一.数学函数 ABS(x) 返回x的绝对值 BIN(x) 返回x的二进制(OCT返回八进制,HEX返回十六进制) CEILING(x) 返回大于x的最小整数值 EXP ...
- 《手把手教你》系列技巧篇(二十九)-java+ selenium自动化测试- Actions的相关操作上篇(详解教程)
1.简介 有些测试场景或者事件,Selenium根本就没有直接提供方法去操作,而且也不可能把各种测试场景都全面覆盖提供方法去操作.比如:就像鼠标悬停,一般测试场景鼠标悬停分两种常见,一种是鼠标悬停在某 ...
- Web 开发人员和设计师必读文章推荐【系列二十九】
<Web 前端开发精华文章推荐>2014年第8期(总第29期)和大家见面了.梦想天空博客关注 前端开发 技术,分享各类能够提升网站用户体验的优秀 jQuery 插件,展示前沿的 HTML5 ...
- WCF技术剖析之二十九:换种不同的方式调用WCF服务[提供源代码下载]
原文:WCF技术剖析之二十九:换种不同的方式调用WCF服务[提供源代码下载] 我们有两种典型的WCF调用方式:通过SvcUtil.exe(或者添加Web引用)导入发布的服务元数据生成服务代理相关的代码 ...
- JAVA之旅(二十九)——文件递归,File结束练习,Properties,Properties存取配置文件,load,Properties的小练习
JAVA之旅(二十九)--文件递归,File结束练习,Properties,Properties存取配置文件,load,Properties的小练习 我们继续学习File 一.文件递归 我们可以来实现 ...
- FreeSql (二十九)Lambda 表达式
FreeSql 支持功能丰富的表达式函数解析,方便程序员在不了解数据库函数的情况下编写代码.这是 FreeSql 非常特色的功能之一,深入细化函数解析尽量做到满意,所支持的类型基本都可以使用对应的表达 ...
随机推荐
- C# 执行oracle sql 语句出现中文不兼容的问题
最近我用C#调用 操作oracle 数据库 出现了一个问题就是 我的查询语中的条件语句 含有中文 字符在C#中查询不了 ,但是在pl sql 中能够正常的查询出来. 这个原因是 C# 执行orccl ...
- 怎样给手机安装fiddler证书
如果需要抓取手机端的HTTPS包,就要在手机上面安装fiddler证书. 1.使用手机连接WiFi做好代理: 2.代理成功后打开手机浏览器: 3.在浏览器输入:http://IP地址:端口号后搜索(如 ...
- MySQL平滑删除数据的小技巧【转】
今天接到一位开发同学的数据操作需求,需求看似很简单,需要执行下面的SQL语句: delete from test_track_log where log_time < '2019-1-7 00: ...
- JdbcTemplate中queryForObject方法返回空结果或不正确结果数量的解决方法
在使用Spirng提供的JdbcTemplate中名为queryForObject API进行数据库查询时有时会抛出如下异常: org.springframework.dao.EmptyResultD ...
- English 动词篇
动词后加to do 和 doing的记忆口诀 一.只能用动名词(ing)作宾语 [口诀] 考虑建议盼原谅,承认推迟没得想. 避免错过继续练,否定完成停欣赏. 禁止想象才冒险,不禁介意弃逃亡. cons ...
- python selenium Chrome模拟手机浏览器
在做移动端页面测试时可以利用Chrome mobile emulation 辅助完成页面的适配问题,但是目前手机市场上的型号居多我们也没有办法通过人工的模式一一的去适配,所以这里考虑到通过自动化的模式 ...
- [转]Windows下安装storm-0.9.1
来源:https://www.cnblogs.com/liuruitao/p/4669657.html Windows下安装storm-0.9.1的详细步骤如下: 1.确定已经正确安装JDK1.6或J ...
- 一起学爬虫——使用xpath库爬取猫眼电影国内票房榜
之前分享了一篇使用requests库爬取豆瓣电影250的文章,今天继续分享使用xpath爬取猫眼电影热播口碑榜 XPATH语法 XPATH(XML Path Language)是一门用于从XML文件中 ...
- 一起学爬虫——通过爬取豆瓣电影top250学习requests库的使用
学习一门技术最快的方式是做项目,在做项目的过程中对相关的技术查漏补缺. 本文通过爬取豆瓣top250电影学习python requests的使用. 1.准备工作 在pycharm中安装request库 ...
- Base64 加解密
import java.io.UnsupportedEncodingException; import org.apache.tomcat.util.codec.binary.Base64; /** ...