Python之旅的第25天(getattribute、item系列、str、repr、format)

今天被虐了,信誓旦旦的去刷题,结果被题按在地板上摩擦,所以继续好好学,好好练习吧。以后的周末时间真的很宝贵了,需要练习的内容有很多,今天真的是深刻体会了每天坚持在这个东东上面做笔记的好处了,忘了翻一翻,生活美滋滋。

一、针对反射的补充

# 关于反射内容的补充
# 昨天详细的说了关于__getattr__  __hasattr__  __setattr__  __delattr__
# 昨天主要针对类和实例化对象,我们都测试了上述函数,是可以的使用的
# 那么针对文件是否也可以正常使用呢?
# 请记住在Python中一切皆为对象,文件当然阔以了
# test.py文件内容:
# def test():
#     print('hello word')
import test as test_obj
print(hasattr(test_obj,'test'))   #返回True
# 这里证明一切皆对象的说法
# 这种作用主要针对于多个人同时开发的时候可以不用等待别人的成果,自己可以先行开始
# 比如test文件中没有定义add方法
# 我们可以采取以下做法
if hasattr(test_obj , 'add'):
    fun = getattr(test_obj,'add')
    fun()
else:
    print('function is coming!!!')

# 上面这些内容我们都是说了调用别的文件,进行反射检测,
# 那么针对我们文件自身是否可以实现反射的方法呢?
# 答案是肯定
# 先定义一个add方法作为测试对象吧
def add(x,y):
    return x+y
import sys
test_1 = sys.modules[__name__]
print(hasattr(test_1,'add'))
# 返回了True,表示可以对自身进行反射
# 其他三个方法是一个样子的

二、关于__getattribute__

# __getattribute__、__getattr__
# 从表面上看,两者看起来很像,那么他们之间的具体关系是什么呢?
# 先进行一个测试吧
# class Test:
#     def __init__(self,age):
#         self.age = age
#
#     def __getattr__(self, item):
#         print('getattr is coming!!!')
#     def __getattribute__(self, item):
#         print('getattribute is coming!!!')
#
# t1 = Test(18)
# 首先我们调用一个这个类有的属性
# t1.age  #交互界面输出:getattribute is coming!!!
# 接着我们调用一个没有的属性
# t1.xxx  #交互界面还是输出:getattribute is coming!!!
# 之前的__getattr__怎么就不执行了呢?

# 下面我们重新定义一下刚才的类,并进行一些修改,
# 增加一个函数方法
# 同时在__getattribute__后面增加 raise AttributeError ''

class Test:
    def __init__(self,age):
        self.age = age
    def test_1(self):
        return self.age
    # def __getattr__(self, item):
    #     print('getattr is coming!!!')
    # def __getattribute__(self, item):
    #     print('getattribute is coming!!!')
        # raise AttributeError('传递报错信息')

t1 = Test(18)
t1.age
print(t1.test_1())
# getattribute is coming!!!
# getattr is coming!!!
# 这里应该注意的是,getattribute是Python中自带的函数
# 我们在执行一个类的属性的时候,会首先执行getattribute进行查找
# 如果存在,那么会直接转入对应属性
# 不存在就会召唤他的小弟__getattr__执行,系统默认的__getattr__是不执行的,我们定义了之后就有了内容

三、关于item系列

class Foo:
    def __getitem__(self, item):
        print('getitem',item)
        return self.__dict__[item]

    def __setitem__(self, key, value):
        print('setitem')
        self.__dict__[key]=value

    def __delitem__(self, key):
        print('delitem')
        self.__dict__.pop(key)

f1=Foo()
print(f1.__dict__)
# f1.name='egon'  #---->setattr-------->f1.__dict__['name']='egon'
f1['name']='egon'#--->setitem--------->f1.__dict__['name']='egon'
f1['age']=18

print('===>',f1.__dict__)

# del f1.name
# print(f1.__dict__)
#
# print(f1.age)
del f1['name']
print(f1.__dict__)

print(f1['age'])
raise S
# 这里应该明白所有对象通过.调用属性的时候会触发__attr__
# 通过字典[]调用时会触发__item__

四、关于str、repr

# 关于str,其实就是内置方法__str__
# 每个类中会有一个默认__str__方法,我们可以通过修改它拿到自己想要的结果
# class People:
#     def __init__(self,name,age):
#         self.name = name
#         self.age = age
# p1 = People('zhaolei',18)
# print(p1)  #<__main__.People object at 0x00000237F29FE908>
# 显然这么一段我们是在是不想看
# 还有其他案例
# a = list('helloworld')
# print(a)
# ['h', 'e', 'l', 'l', 'o', 'w', 'o', 'r', 'l', 'd']
# 其实我们在print的时候本质是触发了str()方法
# 最终触发__str__

# 所以我们针对类中的__str__方法进行修改
class Test:
    def __init__(self,name,age):
            self.name = name
            self.age = age

    def __str__(self):
        return '名字:%s  年龄:%s'%(self.name,self.age)

# 此时我们重新进行实例化并打印
t1 = Test('zhaolei',18)
print(t1)
# 名字:zhaolei  年龄:18
# 此时我们就可以根据自己的需求进行修改,得到自己想要的打印状态

# 下面是repr
class Foo:
    def __init__(self,name,age):
        self.name=name
        self.age=age
    # def __str__(self):
    #     return '折是str'
    def __repr__(self):
        return '名字是%s 年龄是%s' %(self.name,self.age)

f1=Foo('egon',19)
#repr(f1)---->f1.__repr__()
print(f1) #str(f1)---》f1.__str__()------>f1.__repr__()
# 就是如果系统找不到__str__的时候就会找寻__repr__

五、关于format的构造函数

# x='{0}{0}{0}'.format('dog')
#
# print(x)

# class Date:
#     def __init__(self,year,mon,day):
#         self.year=year
#         self.mon=mon
#         self.day=day
# d1=Date(2016,12,26)
#
# x='{0.year}{0.mon}{0.day}'.format(d1)
# y='{0.year}:{0.mon}:{0.day}'.format(d1)
# z='{0.mon}-{0.day}-{0.year}'.format(d1)
# print(x)
# print(y)
# print(z)

# x='{0.year}{0.mon}{0.day}'.format(d1)
# y='{0.year}:{0.mon}:{0.day}'
# z='{0.mon}-{0.day}-{0.year}'

format_dic={
    'ymd':'{0.year}{0.mon}{0.day}',
    'm-d-y':'{0.mon}-{0.day}-{0.year}',
    'y:m:d':'{0.year}:{0.mon}:{0.day}'
}
class Date:
    def __init__(self,year,mon,day):
        self.year=year
        self.mon=mon
        self.day=day
    def __format__(self, format_spec):
        print('我执行啦')
        print('--->',format_spec)
        if not format_spec or format_spec not in format_dic:
            format_spec='ymd'
        fm=format_dic[format_spec]
        return fm.format(self)
d1=Date(2016,12,26)
# format(d1) #d1.__format__()
# print(format(d1))
print(format(d1,'ymd'))
print(format(d1,'y:m:d'))
print(format(d1,'m-d-y'))
print(format(d1,'m-d:y'))
print('===========>',format(d1,'asdfasdfsadfasdfasdfasdfasdfasdfasdfasdfasdfasdfasd'))

六、关于昨天授权的重新注释书写

import time
class Filehandle:
    def __init__(self,file_name , module = 'w+' , encoding = 'utf-8' ):
        self.file = open(file_name,module,encoding = encoding)  #这里的encoding= encoding很重要,这有这样才能满足传入字符串的要求,想想之前在使用open的时候吧
        self.name = file_name
        self.mode = module
        self.encoding = encoding

    def __getattr__(self, item):
        return getattr(self.file,item)
    # 这里的主要作用是,对于我们不需要重新定义的方法,我们就可以正常使用原有的文件操作方式
    # 这样就能保证只修改我们希望修改的部分

    def write(self,line):
        print('------------>',line)
        t=time.strftime('%Y-%m-%d %X')
        self.file.write('%s %s' %(t,line))
    # 这里我们希望在文件的没一句前面增加时间内容,那么久进行了相应的修改

f1=Filehandle('a.txt','w+')
f1.write('测试1行
')
time.sleep(3)
f1.write('测试2行
')
time.sleep(3)
f1.write('测试3行
')

# 2020-03-19 00:35:28 测试1行
# 2020-03-19 00:35:31 测试2行
# 2020-03-19 00:35:34 测试3行

今天就是这些内容了,谢谢各位的认真阅读

原文地址:https://www.cnblogs.com/xiaoyaotx/p/12521554.html