zoukankan      html  css  js  c++  java
  • 面向对象之内置方法

    #python 内置方法      为类内建的函数

    #isinstance 检查obj 是否是类cls 的对象
    class Foo:
    pass
    obj = Foo()
    print(isinstance(obj,Foo))


    #issubclass 检查sub类 是否是father 类的父类
    class Foo():
    pass
    class Bar(Foo):
    pass
    print(issubclass(Bar,Foo))


    #反射 (自省) :程序可以访问,检测和修改它本身状态或行为的一种能力
    #python 中的反射 : 通过字符串的形式操作对象相关的属性 适用于类和对象

    import sys

    class People:
    country = 'china'
    def __init__(self,name):
    self.name = name
    def walk(self):
    print('%s is walking '%self.name)
    p = People('egon')

    #hasattr #检测对象或类是否有这个属性
    print(hasattr(People,'country'))
    print(hasattr(People,'walk'))

    p.sex = 'male'
    print(hasattr(p,'sex')) #p.sex
    print(hasattr(p,'walk')) #p.walk

    #getattr #得到对象或类的某个属性
    res = getattr(People,'country')
    print(res)
    f = getattr(p,'walk')
    print(f)
    f1 = getattr(People,'walk')
    print(f1)
    #setattr #为对象和类设置新的属性
    setattr(p,'age',18)
    print(getattr(p,'age'))
    print(getattr(p,'xxxxx','not found attribute'))

    if hasattr(p,'age'):
    print(getattr(p,'age'))
    #delattr #删除对象或类的属性
    delattr(p,'age')
    print(hasattr(p,'age'))

    #.py文件的两种用法:
    #脚本文件 :可以直接执行当前这个文件,那这个文件就是脚本文件
    #当做模块在另一个程序中调用

    #反射当前模块的成员
    this_module = sys.modules[__name__]
    print(this_module) #拿到这个模块的绝对路径

    print(hasattr(this_module,'p'))
    print(getattr(this_module,'p')) #print(this_module.p) 得到当前模块下的一个对象
    print(__name__)


    #反射的用途
    # 1字符串反射成为一个命令 远程控制
    import sys
    def add():
    print('add')

    def change():
    print('change')

    def search():
    print('search')


    def delete():
    print('delete')

    func_dic={
    'add':add,
    'change':change,
    'search':search,
    'delete':delete
    }
    while True:
    cmd = input('>> :')
    if not cmd:continue
    if cmd in func_dic: # hasattr
    func = func_dic[cmd] #getattr
    func()

    this_module = sys.modules[__name__]
    while True:
    cmd = input('>> :')
    if not cmd:continue
    if hasattr(this_module,cmd):
    func =getattr(this_module,cmd)
    func()


    #2可插拔机制:ftpserver ftpclient
    #反射的好处就是,可以事先定义好接口,接口只有在被完成之后才会真正执行,这实现了即插即用
    #即你可以事先把主要的逻辑写好(只定义接口),然后后期再实现接口

    #3以字符串的形式导入模块 动态导入模块
    #利用内置函数 不推荐
    m = input('module :')
    m1 = __import__(m)
    print(m1.time())
    # 官方推荐
    import importlib
    t = importlib.import_module(m)
    print(t.time())

    # __setattr__ __delattr__ __getattr__
    #与property的应用场景的区别:
    #property可以自定义对象对于所属类的一个属性的访问和操作
    #下述三者可以自定义类的所有属性被操作的权限
    #都可以应用到 定制自己想要的数据类型
    class Foo:
    def __init__(self,name):
    self.name = name
    def __setattr__(self,key,value): #添加或修改属性会触发它的执行 可以限制所有属性设置时的条件
    print('---------setter------key:%s,value:%s'%(key,value))

    self.__dict__[key]=value
    def __delattr__(self,item): #删除属性可以触发它的执行 可以限制所有属性在什么条件下才能删除
    print('--delattr-----%s'%item)
    print(self.__dict__.pop(item))
    def __getattr__(self,item): #属性不存在的情况下才会触发
    print('---------getsttr----%s'%item)


    f =Foo('egon')
    f.age = 18
    f.sex = 'male'
    print(f.__dict__)

    del f.age
    print(f.__dict__)

    print(f.xxxxxxx)

    #定制自己的数据类型 (二次加工标准类型) (包装)
    #1基于继承实现
    class List(list):
    def append(self,p_obj):
    if not isinstance(p_obj,int):
    raise TypeError('must be int')
    super().append(p_obj)
    def insert(self, index:int, p_object:int):
    #print(insert.__annotations__)
    if not isinstance(p_object,int):
    raise TypeError('must be int')
    super().insert(index,p_object)

    l = List([1,2])
    l.append(3)
    print(l)


    l.insert(0,8)
    print(l)
    l.insert(2,9)
    print(l)


    #不能用继承,来实现open函数的功能
    f = open('a.txt','w')
    print(f)
    f.write('1111111111')
    #2授权的方式实现定制自己的数据类型
    #授权是包装的一个特性,包装一个类型,通常是对已存在的类型的一些定制,这种方法可以新建,修改或删除原有产品的功能
    #其他则保持原样。授权的过程,即是所有更新的功能都是由新类的某部分来处理,但已存在的功能就授权给对象的默认属性
    import time
    class Open:
    def __init__(self,file_path,m = 'r',encode = 'utf8'):
    self.file_path = file_path
    self.mode = m
    self.encoding = encode
    self.x = open(file_path,mode = m,encoding = encode)
    def write(self,line):
    # print('f自己的write',line)
    t = time.strftime('%y-%m-%d %X')
    self.x.write('%s %s'%(t,line))

    def __getattr__(self,item):
    return getattr(self.x,item)


    f = Open('a.txt','r')
    # print(f)
    f.write('1111111111111 ')
    f.write('1111111111111 ')
    f.write('1111111111111 ')
    f.write('1111111111111 ')
    f.write('1111111111111 ')
    f.write('1111111111111 ')

    f.seek(0)
    print(f.read())
    # 基于授权定制自己的列表类型,要求定制的自己的__init__方法,
    # 定制自己的append:只能向列表加入字符串类型的值
    # 定制显示列表中间那个值的属性(提示:property)
    # 其余方法都使用list默认的(提示:__getattr__加反射)


    class List:
    def __init__(self,*args):
    self.x =list(args)
    def append(self,value):
    if not isinstance(value,str):
    raise TypeError('must be str')
    self.x.append(value)
    @property
    def mid(self):
    return self.x[int(len(self.x)/2)]
    def __getattr__(self,item):
    return getattr(self.x,item)
    def __str__(self):
    return str(self.x)




    l = List(1,2,3,4,5,6)
    print(l)

    l.append('123')
    l.append('123')
    l.append('123')
    l.append('123')
    print(l)
    print(l.mid)

    l.insert(0,'9')
    print(l)
    
    



    #__getitem__ __setitem__ __delitem__
    # 把对象操作属性模拟成字典的格式
    class Foo:
    def __init__(self,name):
    self.name = name
    def __getitem__(self, item):
    return self.__dict__[item]
    def __setitem__(self, key, value):
    self.__dict__[key] = value
    def __delitem__(self, key):
    self.__dict__.pop(key)

    f = Foo('egon')
    print(f['name'])
    f['age']= 18
    print(f.__dict__)
    del f['age']
    print(f.__dict__)
    #__str__ __repr__ __format__
    format_dict={
    'nat':'{obj.name}-{obj.addr}-{obj.type}',#学校名-学校地址-学校类型
    'tna':'{obj.type}:{obj.name}:{obj.addr}',#学校类型:学校名:学校地址
    'tan':'{obj.type}/{obj.addr}/{obj.name}',#学校类型/学校地址/学校名
    }
    class School:
    def __init__(self,name,addr,type):
    self.name=name
    self.addr=addr
    self.type=type

    def __repr__(self):
    return 'School(%s,%s)' %(self.name,self.addr)
    def __str__(self):
    return '(%s,%s)' %(self.name,self.addr)

    def __format__(self, format_spec):
    # if format_spec
    if not format_spec or format_spec not in format_dict:
    format_spec='nat'
    fmt=format_dict[format_spec]
    return fmt.format(obj=self)

    s1=School('oldboy1','北京','私立')
    print('from repr: ',repr(s1))
    print('from str: ',str(s1))
    print(s1)


    str函数或者print函数--->obj.__str__()
    repr或者交互式解释器--->obj.__repr__()
    如果__str__没有被定义,那么就会使用__repr__来代替输出
    注意:这俩方法的返回值必须是字符串,否则抛出异常

    print(format(s1,'nat'))
    print(format(s1,'tna'))
    print(format(s1,'tan'))
    print(format(s1,'asfdasdffd'))

    #__slots__
    # 它所产生的对象只能设置__slots__里面的属性,并且对象没有命名空间
    # 大多数情况下,你应该只在那些经常被使用到 的用作数据结构的类上定义__slots__比如在程序中需要创建某个类的几百万个实例对象 。
    # 关于__slots__的一个常见误区是它可以作为一个封装工具来防止用户给实例增加新的属性。
    # 尽管使用__slots__可以达到这样的目的,但是这个并不是它的初衷。 更多的是用来作为一个内存优化工具

    class People:
    __slots__=['x','y','z']

    p=People()
    print(People.__dict__)

    p.x = 1
    p.y =2
    p.z = 3
    print(p.x,p.y,p.z)
    # print(p.__dict__)
    # p.d= 9
    # print(p.d)

    #__iter__ __next__
    # #实现迭代器协议
    from collections import Iterable,Iterator
    class Foo:
    def __init__(self,start):
    self.start = start
    def __iter__(self):
    return self
    def __next__(self):
    if self.start > 10:
    raise StopIteration
    n = self.start
    self.start += 1
    return n

    f = Foo(0)
    for i in f:
    print(i)


    # 实现range
    class Bar:
    def __init__(self,start,end):
    self.start = start
    self.end = end
    def __iter__(self):
    return self
    def __next__(self):
    if self.start > (self.end-1):
    raise StopIteration
    n = self.start
    self.start += 1
    return n

    b = Bar(1,6)
    for i in b:
    print(i)

    #__doc__ __module__ __class__
    class Foo:
    'Foo class'
    def __init__(self):
    pass
    f = Foo()
    print(f.__doc__)
    print(f.__module__)
    print(f.__class__)
    #__del__ 析构方法 当对象在内存中被释放时,自动触发执行

    class Open:
    def __init__(self,filepath,mode = 'r',encode = 'utf8'):
    self.f = open(filepath,mode = mode ,encoding = encode)
    def write(self):
    pass
    def __getattr__(self, item):
    return getattr(self.f,item)
    def __del__(self): #此方法一般无须定义,python会在对象被释放时,内存定时回收垃圾
    print('----------->del')
    self.f.close()

    f = Open('a.txt','r')

    print('ttttttttttt')
    f1 = f
    del f #会立即触发类的__del__ 函数


    # f.read()
    print('ggggggggg')


    #__call__ 对象后面加括号,触发执行

    class Foo:
    def __init__(self):
    pass
    def __call__(self,*args,**kwargs):
    print('call')
    f = Foo()
    f()


    #metaclass
    # type称为元类,是所有类的类,利用type模拟class关键字的创建类的过程
    def run(self):
    print('%s is running '%self)
    class_name = 'Bar'
    bases = (object,)
    class_dict ={
    'x':1,
    'run':run
    }
    Bar = type(class_name,bases,class_dict)
    print(Bar)
    print(type(Bar))

    s = type('spam',(),{})
    print(s)




    # 自定义元类
    class Mymeta(type):
    def __init__(self,class_name,class_bases,class_dict):
    for key in class_dict:
    if not callable(class_dict[key]):continue
    if not class_dict[key].__doc__:
    # raise TypeError('没有注释啊')
    pass

    class Foo(metaclass=Mymeta): #type.__init__(self,class_name,class_bases,class_dict)
    x = 1
    def run(self):
    'run function'
    print('runing')

    Foo = Mymeta('Foo',(object,),{'x':1,'run':run})
    print(Foo.__dict__)

    # 类实例化对象时的init自动触发机制
    class Mymeta(type):
    def __init__(self,class_name,class_bases,class_dict):
    pass
    def __call__(self, *args, **kwargs): #对象后面加括号,触发执行
    obj = self.__new__(self)
    self.__init__(obj,*args,**kwargs)
    return obj
    class Foo(metaclass=Mymeta):
    x = 1
    def __init__(self,name):
    self.name = name
    def run(self):
    print('running')
    print(Foo)
    f = Foo('egon')
    print(f)



    #__enter__ __exit__
    # 上下文管理协议
    with open('a.txt') as f:
    'fffffffffff'


    class Foo:
    def __enter__(self):
    print('=====================>enter')
    return 1111111111
    def __exit__(self, exc_type, exc_val, exc_tb):
    print('exit')
    print('exc_type',exc_type)
    print('exc_val',exc_val)
    print('exc_tb',exc_tb)
    return True
    with Foo(): #res = Foo().__enter__()
    pass




    with Foo() as obj: #obj = res
    print('with foo 的子代码块',obj)
    raise NameError('名字没有定义')
    print('yyyyyyyyyyy')


    #实现上下文管理协议
    import time
    class Open:
    def __init__(self,file_path,m = 'r',encode = 'utf8'):
    self.file_path = file_path
    self.mode = m
    self.encoding = encode
    self.x = open(file_path,mode = m,encoding = encode)
    def write(self,line):
    # print('f自己的write',line)
    t = time.strftime('%y-%m-%d %X')
    self.x.write('%s %s'%(t,line))

    def __getattr__(self,item):
    return getattr(self.x,item)
    def __enter__(self):
    return self
    def __exit__(self, exc_type, exc_val, exc_tb):
    self.close()
    return True


    with Open('a.txt','w') as file:
    file.write('dddddddddddddd ')
    file.write('dddddddddddddd ')
    file.write('dddddddddddddd ')
    print('ggggggg')
    file.write('dddddddddddddd ')
     #__eq__ 和__hash__
    继承obj的类自带哈希属性,将类所有的属性值(字符串)摘要成为哈希值
    自己定义的类没有哈希属性
    假设有100个person的对象,
    若两个对象的obj1,obj2的name和sex属性相同
    即obj1.name==obj2.name and obj1.sex==obj2.sex
    我们认为两个对象为同一个对象,已知一个列表中的100个对象,对这100个对象进行去重。
    class Person:
    def __init__(self,name,age,sex,weight):
    self.name = name
    self.age = age
    self.sex = sex
    self.weight = weight
    def __eq__(self, other):
    if self.name == other.name and self.sex == other.sex:
    return True
    def __hash__(self): #自定义哈希方法
    return (self.name,self.sex).__hash__()
    def __str__(self):
    return str(self.__hash__())

    a1 = Person('alex',18,'male',60)
    a2 = Person('alex',18,'male',60)
    print(set([a1,a2])) #会自动触发类中的eq属性和hash属性,比较两者的属性值
    print(a1,a2) #打印两个对象的哈希值
     


  • 相关阅读:
    UVA 11019 Matrix Matcher ( 二维字符串匹配, AC自动机 || 二维Hash )
    蓝桥杯 修改数组 (巧用并查集)
    luoguP3242 [HNOI2015]接水果
    CF757F Team Rocket Rises Again
    luoguP2597 [ZJOI2012]灾难
    luoguP4103 [HEOI2014]大工程
    luoguP3233 [HNOI2014]世界树
    luoguP2495 [SDOI2011]消耗战
    CF613D Kingdom and its Cities
    51nod 1584 加权约数和
  • 原文地址:https://www.cnblogs.com/liuguniang/p/6792082.html
Copyright © 2011-2022 走看看