python之路--day23--面向对象高级

内置函数补充:

  isinstance:判断对象是不是类的实例

  issubclass:判断类是否是一个类的子类

1,反射

   指程序可以访问,检测,修改它本身状态或行为的一种能力(自省)

 1.1,python面向对象中的反射:通过字符串的形式操作对象相关的属性

  1.1.1  四个可以实现自省的函数

    

hasattr(object,name)
判断object中有没有一个name字符串对应的方法或属性,返回布尔值

class test():
    name = 'egon'
    def run(self):
        return 'Helloword'

t = teat()

print(hasattr(t,'run')) 
True

print(hasattr(t,'Helloword'))
False
 
hasattr(object,name)
class teat():
    name = 'egon'
    def run(self):
        return 'helloword'

t= test()
getattr(t,'name') #获取name属性。存在就打印出来

getattr(t,'run') #获取run方法,存在就打印方法的内存地址,,加括号可以直接运行

getattr(t,‘age’) #获取一个不存在的属性。报错


getattr(t,'age','18')  #若属性不存在,返回一个默认值
getattr(object,name[,default])
给对象的属性赋值,若属性不存在,就先创建在赋值
class test():
    name="xiaohua"
    def run(self):
          return "HelloWord"

t=test()

hasattr(t,'age'#判断属性是否存在

setattr(t,'age','18') #为属性赋值,没有返回值

hasattr(t,'age')#属性存在了
setattr(object,name,values)
删除object的属性,name对应的属性不存在就报错
delattr(object,name)
class Foo(object):
    staticField = "old boy"

    def __init__(self):
        self.name = 'wupeiqi'

    def func(self):
        return 'func'

    @staticmethod
    def bar():
        return 'bar'


print(getattr(Foo, 'staticField'))
print(getattr(Foo, 'func'))
print(getattr(Foo, 'bar'))
类也是对象

 

 

2.__str__方法

   print一个类的实例化对象的时候,会执行类下的__str__函数属性

   这个方法必须有一个返回值

def People:
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex
    def __str__(self):
        return '<名字:%s 年龄:%s 性别: %s>
%(self.name,self.age,self.sex)
__str__方法

 

 

 

  

3.__del__方法

  在一个类的对象被删除的条件下,类下的__del__方法会自动执行

  一般用在程序使用完申请的系统资源之后,释放系统资源

class People:
    def __init__(self,name.age,sex):
        self.name= name
        self.age=age
        self.sex=sex 
    def __del__(self): #在对象被删除的条件下,自动执行
        print('__del__')
__del__方法

 

4.exec方法

  exec(object,global,local)

  object --字符串形式的命令

  global--全局作用域,字典形式--存放object内定义的全局名称

  local---局部作用域,字典形式--存放object内定义的局部名称

  

#可以把exec命令的执行当成是一个函数的执行,会将执行期间产生的名字存放于局部名称空间中--前提是被指定为全局名称
g={
    'x':1,
    'y':2
}
l={}

exec('''
global x,z
x=100
z=200

m=300
''',g,l)

print(g) #{'x': 100, 'y': 2,'z':200,......}
print(l) #{'m': 300}
exec()

 

5.元类

  概念理解:

      python中一切都是对象。类本身也是对象。使用class关键字时,python解释器在加载class时创建一个对象(指的是类,而不是类的实例),所以类也是对象,所以:    

  • 把类赋值给一个变量

  • 把类作为函数参数进行传递

  • 把类作为函数的返回值

  • 把类作为容器类型的元素
class Foo:
    pass

f1 = Foo()#f1是用过Foo类实例化的对象

#type函数可以查看类型,也可以用来查看对象的类
print(type(f1)) # 输出:<class '__main__.Foo'>     表示,obj 对象由Foo类创建
 print(type(Foo)) # 输出:<type 'type'>  
查看一个类的类型

 

5.1 什么是元类

  元类就是类的类

  type是python的一个内建元类,用来直接控制生成类,python中任何class定义的类都是type实例化的对象

 

5.2创建类的两种方式

  1,使用class关键字

  2, 手动模拟class创建类的过程:将创建类的步骤拆分开,手动去创建

  概念理解:

    类的三要素:1.类名----class_name = 'chinses'

          2.类的父类----class_bases = (object,)

          3.执行类体代码产生的名字---class_dic

              class_body (类体代码使用字符串表示,调用exec方法,得到类体内的名称---没有指定都是局部名称)

"""
country='China'
def __init__(self,name,age):
    self.name=name
    self.age=age
def talk(self):
    print('%s is talking' %self.name)
"""
class_body

     步骤:1,处理类体代码得到名称空间

       2,调用元类type(元类可以自定义)来产生类chinese

 

Foo=type(class_name,class_bases,class_dic) 

#实例化type得到对象Foo,即我们用class定义的类Foo print(Foo) print(type(Foo)) print(isinstance(Foo,type)) ''' <class '__main__.Chinese'> <class 'type'> True '''

 

 

 

 5.3 自定义元类控制类的调用

  知识储备:__call__,调用对象,会自动触发对象的绑定方法__call__的执行

class Foo:
    def __call__(self,*args,**keargs):
        print('__call__',args,kwargs)

#调用对象,会自动触发对象下的绑定方法__call__的执行
#然后将对象本身当做第一个参数传给self,将调用对象时括号内的值传给*args和**kwargs
__call__方法

 

 5.3.1  自定义元类:

  步骤1,定义元类,控制类的创建  

 

Foo=type(class_name,class_bases,class_dic) 
#实例化type得到对象Foo,即我们用class定义的类Foo
#上述表达式  等价于 class Foo

class Mymeta(type):  #继承默认元类的属性
    def __init__(self,class_name,class_bases,class_dic):
        #定制类的创建规则
        if "__doc__" not in class_dic or not class_dic.get('__doc__'):
            raise TypeError('必须为类指定文档注释')
        if not class_name.istitle():
            raise TypeError('类首字母必须大写')

        super(Mymeta,self).__init__(class_name,class_bases,class_dic)
        #继承type的代码

 

 步骤2,__call__方法的知识。
    
class People(object,metaclass=type):
    def __init__(self,name,age):
        self.name=name
        self.age=age

    def __call__(self, *args, **kwargs):
        print(self,args,kwargs)


# 调用类People,并不会出发__call__
obj=People('egon',18)

# 调用对象obj(1,2,3,a=1,b=2,c=3),才会触发对象的绑定方法obj.__call__(1,2,3,a=1,b=2,c=3)
obj(1,2,3,a=1,b=2,c=3) #打印:<__main__.People object at 0x10076dd30> (1, 2, 3) {'a': 1, 'b': 2, 'c': 3}

#总结:如果说类People是元类type的实例,那么在元类type内肯定也有一个__call__,会在调用People('egon',18)时触发执行,然后返回一个初始化好了的对象obj

 

步骤3,自定义元类,控制类的调用(实例化)的过程
class Mymeta(type):  #继承默认元类的属性
    def __init__(self,class_name,class_bases,class_dic):
        #定制类的创建规则
        if "__doc__" not in class_dic or not class_dic.get('__doc__'):
            raise TypeError('必须为类指定文档注释')
        if not class_name.istitle():
            raise TypeError('类首字母必须大写')

        super(Mymeta,self).__init__(class_name,class_bases,class_dic)
        #继承type的代码

    def __call__(self, *args, **kwargs):
        #1,实例化People,产生空对象obj
        obj = object.__new__(self)
        #2,调用People下的函数__init__,初始化obj
        self.__init__(obj,*args,**kwargs)
        #3,返回初始化之后的obj
        return obj

单例模式

  指的是同一个类实例多长的结果指向同一个对象,用于节省内存空间

如果我们从配置文件中读取配置来进行实例化,在配置相同的情况下,就没有必要重复产生对象浪费内存


#settings.py文件内容如下
HOST='1.1.1.1'
PORT=3306

import setting
class Mysql:
    __instance = None
    def __init__(self,host,port):
        self.host = host
        self.port = port

    @classmethod
    def singleton(cls):
        if not cls.__instance:
            cls.__instance = cls(setting.HOST,setting.PORT)#产生一个实例化对象
        return cls.__instance

obj1=Mysql('1.1.1.2',3306)
obj2=Mysql('1.1.1.3',3307)
print(obj1 is obj2) #False

obj3=Mysql.singleton()
obj4=Mysql.singleton()
print(obj3 is obj4) #True
不依赖元类的单例模式

 

 

 

        

 

posted @ 2018-04-17 17:32  木夂口  阅读(121)  评论(0编辑  收藏  举报
levels of contents