29 内置方法 eval | exec 元类 单例

eval与exec内置方法

  将字符串作为执行目标,得到响应结果

  eval常用作类型转换:该函数执行完有返回值

  exec拥有执行更复杂的字符串:可以形成名称空间

eval内置函数的使用场景:
   1.执行字符串会得到相应的执行结果
   2.一般用于类型转化,得到dict、list、tuple等

dic_str = "{‘a‘: 1, ‘b‘: 2, ‘c‘: 3}"
print(eval(dic_str))

list_str = "[1, 2, 3, 4, 5]"
print(eval(list_str))

tuple_str = "(1, 2, 3, 4, 5)"
print(eval(tuple_str))

exec应用场景
 1.执行字符串没有执行结果(没有返回值)
 2.将执行的字符串中产生的名字形成对应的局部名称空间

source = ‘‘‘
name = ‘Bob‘
age = 20
‘‘‘
class A:
    pass
a = A()

dic = {}

# 可以操作全局与局部两个名称空间,一般不用关心全局名称空间
exec(source, {}, dic)
a.__dict__ = dic
print(a.__dict__)   # {‘name‘: ‘bob‘, ‘age‘: 20}
print(a.name)
print(a.age)

元类

元类:类的类
  通过class产生的类,也是对象,而元类就是用来产生该对象的类

  类是type的对象,可以通过type(参数)来创建类

local_str = """
def __init__(self, name, age):
    self.name = name
    self.age = age
def study(self):
    print(self.name + ‘在学习‘)
"""
local_dic = {}
exec(local_str, {}, local_dic)
Student = type(‘Student‘, (), local_dic)
print(Student)

type创建类

# type(name, bases, namespace)

s = ‘‘‘
my_a = 10
my_b = 20
def __init__(self):
    pass
@classmethod
def print_msg(cls, msg):
    print(msg)
‘‘‘
namespace = {}
exec(s, {}, namespace)

Student = type(‘Student‘, (object, ), namespace)

stu = Student()

自定义元类

  所有自定义的类本身也是对象,是元类的对象,所有自定义的类本质上是由元类实例化出来了

  控制类的产生过程,以及该类对象的产生过程

# 元类:所有自定义的类本身也是对象,是元类的对象,所有自定义的类本质上是由元类实例化出来了
Student = type(‘Student‘, (object, ), namespace)

class MyMeta(type):
    # 在class Student时调用:Student类的创建 => 来控制类的创建

    # 自定义元类,重写init方法的目的:
    # 1.该方法是从type中继承来的,所以参数同type的init
    # 2.最终的工作(如果开辟空间,如果操作内存)还是要借助type
    # 3.在交给type最终完成工作之前,可以对类的创建加以限制 *****
    def __init__(cls, class_name, bases, namespace):
        # 目的:对class_name | bases | namespace加以限制 **********************
        super().__init__(class_name, bases, namespace)

    # 在Student()时调用:Student类的对象的创建 => 来控制对象的创建

    # 自定义元类,重写call方法的目的:
    # 1.被该元类控制的类生成对象,会调用元类的call方法
    # 2.在call中的返回值就是创建的对象
    # 3.在call中
    #       -- 通过object开辟空间产生对象
    #       -- 用被控制的类回调到自己的init方法完成名称空间的赋值
    #       -- 将修饰好的对象反馈给外界
    def __call__(cls, *args, **kwargs):
        # 目的:创建对象,就可以对对象加以限制 **********************
        obj = object.__new__(cls)  # 通过object为哪个类开辟空间
        cls.__init__(obj, *args, **kwargs)  # 调回当前被控制的类自身的init方法,完成名称空间的赋值
        return obj

# 问题:
# 1.继承是想获得父级的属性和方法,元类是要将类的创建于对象的创建加以控制
# 2.类的创建由元类的__init__方法控制
#        -- 元类(class_name, bases, namespase) => 元类.__init__来完成实例化
# 3.类的对象的创建由元类的__call__方法控制
#         -- 对象产生是需要开辟空间,在__call__中用object.__new__()来完成的
class Student(object, metaclass=MyMeta):
    pass

# class Student:  <=>  type(class_name, bases, namespace)

  控制类、类的对象 产生过程

class MyMeta(type):
    # 控制类的创建过程
    def __init__(cls, class_name, bases, namespace):
        print(cls, class_name, bases, namespace)
        super().__init__(class_name, bases, namespace)

    def __call__(cls, *args, **kwargs):
        obj = object.__new__(cls)
        cls.__init__(obj, *args, **kwargs)
        return obj

# Student类与Student类的对象产生都可以备元类MyMeta控制
class Student(metaclass=MyMeta):
    def __init__(self, name, age):
        self.name = name
        self.age = age
stu = Student(‘owen‘, 18)
print(stu.name)

元类的应用

# 单例1class MyMeta(type):
    def __call__(cls, *args, **kwargs):
        if not hasattr(cls, ‘instance‘):
            cls.instance = cls.__new__(cls)
            cls.instance.__init__(*args, **kwargs)
        return cls.instance

class A(metaclass=MyMeta):
    def __init__(self):
        self.ip = ‘1.1.1.0‘

单例

  一个类只能产生一个实例
  为什么要有单例:
    1.该类需要对象的产生
    2.对象一旦产生,在任何位置再实例化对象,只能得到第一次实例化出来的对象
    3.在对象唯一创建后,可以通过属性修改或方法间接修改属性,来完成数据的更新,不能通过实例化方式更新数据

# 单例2class Song:
    __instance = None
    def __init__(self):
        pass
    @classmethod
    def getInstance(cls):
        if cls.__instance == None:
            cls.__instance = cls()
        return cls.__instance
s1 = Song.getInstance()
s2 = Song.getInstance()
print(s1, s2)

# 单例3

def singleton(cls):
    _instance = None
    def getInstance(*args, **kwargs):
        nonlocal _instance
        if _instance == None:
            _instance = cls(*args, **kwargs)
        return _instance
    return getInstance

@singleton
class A:
    def __init__(self, num):
        self.num = num
print(A(1), A(2), A(3))

# 单例4

class A:
    __instance = None
    def __new__(cls, *args, **kwargs):
        if cls.__instance == None:
            cls.__instance = super().__new__(cls)
        return cls.__instance
print(A(), A())

# 单例5

# single_module.py
class Single:
    pass
singleton = Single()

# 测试文件
from single_module import singleton
print(singleton)
print(singleton)

原文地址:https://www.cnblogs.com/zhouyongv5/p/10776467.html

时间: 2024-08-26 17:45:26

29 内置方法 eval | exec 元类 单例的相关文章

反射、自定义内置方法来定制类的功能、元类

一.反射 1. 定义:通过字符串来操作类或者对象属性 2. 方法:hasattr.getattr.setattr.delattr 3. 使用方法: 1 class People: 2 def __init__(self,name): 3 self.name=name 4 def put(self): 5 print('%s is putting'%self.name) 6 def get(self): 7 print('%s get sth'%self.name) 8 def run(self)

what&#39;s the python之基本运算符及字符串、列表、元祖、集合、字典的内置方法

计算机可以进行的运算有很多种,运算按种类可分为算数运算.比较运算.逻辑运算.赋值运算.成员运算.身份运算.字符串和列表的算数运算只能用+和*,字典没有顺序,所以不能进行算数运算和比较运算.比较运算中==比较的是值,is比较的是id.比较运算只能在同种类型下进行比较.字符串的比较是按照顺序依次进行比较.逻辑运算的顺序先后为要用括号来表示. 基本运算符如下: 算术运算 以下假设a=10,b=20 比较运算 以下假设a=10,b=20 赋值运算 逻辑运算  成员运算 身份运算 what's the 内

Python类的内置方法

目录 1.new.init 2.str.repr 3.call 4.del 5.iter.next 6.getitem.setitem.delitem 7.getattr.setattr.delattr 8.getatrribute 9.enter.exit 10.get.set.delete.描述符(研究中,待补充) **(为了方便和美观,省略了各内置方法前后的__双下划线)** 1.new.init __new__方法是真正的类构造方法,用于产生实例化对象(空属性).重写__new__方法可

python 类中内置方法的重写

为达成目的,经常会在类中将一些内置方法进行重写,最常见的例如__setattr__,下面就通过内置属性,来查看重写会带来什么变化 先定义一个测试用的类,代码如下 class base: def __init__(self): pass inspect.getmembers(base): # 查看内置属性 打印结果如下 ('__class__', <class 'type'>) ('__delattr__', <slot wrapper '__delattr__' of 'object'

[python] 类常用的内置方法

内置方法 说明 __init__(self,...) 初始化对象,在创建新对象时调用 __del__(self) 释放对象,在对象被删除之前调用 __new__(cls,*args,**kwd) 实例的生成操作 __str__(self) 在使用print语句时被调用 __getitem__(self,key) 获取序列的索引key对应的值,等价于seq[key] __len__(self) 在调用内联函数len()时被调用 __cmp__(stc,dst) 比较两个对象src和dst __ge

Python之面向对象:类的内置方法

1.def __add__(self,other): c1+c2 两个实例的加法操作就是执行__add__()方法 2.__str__(self): print一个实例的时候,执行的是__str__()这个内置方法 eg: class Vector(object): def __init__(self,a,b): self.a = a self.b = b def __str__(self): return 'Vector(%d,%d)'%(self.a,self.b) def __add__(

类的属性、类的方法、类的内置方法

类的属性 变量在类中称为类的属性,函数在类中称为类的方法,类的属性分为以下几种: (1) 公有属性:在类中和类外都能调用的属性,定义的时候与变量的定义一致,如 color = 'yellow'(2) 私有属性:不能在类外及被类以外的函数调用,定义的时候以双下划线开头,如__color = 'yellow' (3) 内置属性: 由系统在定义类的时候默认添加的,定义的时候以前后双下划线构成,如 dict #!/usr/bin/env python class People(object): colo

内置函数—eval、exec、compile

内置函数----eval.exec.compile eval()将字符串类型的代码执行并返回结果.print(eval('1+2+3+4'))输出:10 exec() 将字符串类型的代码执行.print(exec("1+2+3+4"))exec("print('hello,world')")指定global参数code = '''import os print(os.path.abspath('.'))'''code = '''print(123)a = 20pri

几个类的内置方法

# 类的内置方法 # 双下方法 # __str__ # 当类中定义了__str__方法后,print(这个类对象时),会调用__str__. 或者格式化%s输出对象时,都会触发__str__ # __repr__ # 当类中定义了__repr__方法后,print(repr(a)),就会调用a对象中的__repr__()方法.格式化输出用%r时同样会调用__repr__ # 同样对象中如果没有定义__repr__方法,那么就会调用父类中的__repr__ # __repr__是__str__的备