学习总结

课上练习整理

import datetime
import time
from functools import wraps #wraps可以把原函数对象的指定属性复制给包装函数对象

# start = datetime.datetime.now()
# delta = (datetime.datetime.now() -start).total_seconds()

def add(x,y):
    time.sleep(2)
    return x + y

#装饰器
def logger(fn):
    def wrapper(*args):
        z = fn(*args)
        return z
    return wrapper

#装饰器
def logged(func):
    @wraps(func)#原函数就是f,使用@wraps可以把f的属性复制给func对象
    def logging(*args, **kwargs):
        print(1, func.__name__)
        return func(*args, **kwargs) #这里不但可以返回一个像我上面写的z= fn(*args,**kwargs),即z,也可以直接返回一个函数
    return logging
@logged
def f(x):
    """This is a test model"""
    return 'ok'
print(f.__name__) #f
print(f.__doc__)  #This is a test model

def deltatime(fn):
    @wraps(fn)
    def wrapper(*args, **kwargs):
        start = datetime.datetime.now()
        ret = fn(*args, **kwargs) #测试,这里如果直接使用return返回对象的话,下面的语句块就不会执行了
        delta = (datetime.datetime.now() - start).total_seconds()
        print('The demo execute time is {}'.format(delta)) #按照自己的思路想把delta,print和wrapper函数对齐,但是报错
        return ret
    return wrapper

@deltatime # add = deltatime(add)
def add(x, y):
    time.sleep(2)
    return x + y
print(add(3,5))

 

 


import time
import datetime
from functools import wraps

class TimeIt:
   def __init__(self, fn):
      self.fn = fn
      # self.__doc__ = fn.__doc__ #直接修改,就可以使用被装饰函数的属性,动态增减,添加一个,可以看到一个,如果就动态增加doc的话,name的话看不到
      wraps(fn)(self)
   # def __enter__(self):
   #  self.start = datetime.datetime.now()
   #  return self

   # def __exit__(self, exc_type, exc_val, exc_tb):
   #  self.delta = (datetime.datetime.now() - self.start).total_seconds()
   #  print('This demo\'s time is {} '.format(self.delta))
   #  pass

   def __call__(self, *args, **kwargs):
      self.start = datetime.datetime.now()
      ret = self.fn(*args, **kwargs)
      self.delta = (datetime.datetime.now() - self.start)
      print('This second demo\'s time is {}'.format(self.delta)) #This second demo's time is 0:00:01.000058
      return ret

@TimeIt
def add(x,y):
   """This is a add function"""
   time.sleep(1)
   return x + y

add(4,5)
# print(add.__doc__) #This is a add function
# print(add.__name__) #add
# print(add.__call__) #<bound method TimeIt.__call__ of <__main__.TimeIt object at 0x00000000010C0780>>
#应用场景:
# 1、增强功能:
#  在代码执行的前后增加代码,以增强其功能。类似装饰器的功能
# 2、资源管理:
#  打开了资源需要关闭,例如文件对象、网络连接、数据库连接的
# 3、权限验证:
#  在执行代码之前,做权限的验证,在__enter__中处理



class A:
    def __init__(self):
        self.a1 = 'a1'
        print('A.init')

    def __get__(self, instance, owner):
        print("A.__get__{} {} {}".format(self, instance, owner)) #self指的是A的实例,owner是B类,instance是说明
        # return 1

class B:
    x = A()
    def __init__(self):
        print('B.init')

# print(B.x)  #A.init,A.__get__<__main__.A object at 0x00000000010954E0> None <class '__main__.B'>, None:这个None是get方法没有给返回值,默认return None

# print(B.x.a1) #报错:AttributeError: 'NoneType' object has no attribute 'a1'

b = B()
print(b.x) # A.init,B.init,A.__get__<__main__.A object at 0x00000000008454E0> <__main__.B object at 0x0000000000845518> <class '__main__.B'>,None  #打印结果解释:定义了__get__方法,类A就是一个描述器,对类或者类B的实例的x属性读取,称为对类A的实例的访问就会调用__get__方法




class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y


    def __str__(self):
        return "Point({}, {})".format(self.x, self.y)

    def show(self):
        print(self)
        # return self
p1 = Point(4,5)
p2 = Point(10,10)
#print(p1, p2) #打印出字符串 Point(4, 5) Point(10, 10)
#print(repr(p1), repr(p2), sep = '\n') #打印出实例对象 <__main__.Point object at 0x000000000109E978>   <__main__.Point object at 0x00000000010A52E8>

setattr(p1, 'y', 16)
setattr(p1, 'z', 10)
print(getattr(p1, '__dict__')) #{'y': 16, 'z': 10, 'x': 4}

#动态调用方法:
if hasattr(p1, 'show'):
    getattr(p1, 'show')()

#动态增加方法
#为类增加方法

if not hasattr(Point, 'add'):
    setattr(Point, 'add', lambda self,other:Point(self.x + other.x, self.y + other.y))

# print(Point.add) #<function <lambda> at 0x00000000010EA6A8>
# print(p1.add) #<bound method <lambda> of <__main__.Point object at 0x00000000010F5630>>
print(p1.__dict__) #{'z': 10, 'y': 16, 'x': 4}
print(Point.__dict__) # {'__module__': '__main__', '__doc__': None, '__str__': <function Point.__str__ at 0x000000000107A8C8>, 'show': <function Point.show at 0x000000000107A950>, '__weakref__': <attribute '__weakref__' of 'Point' objects>, '__init__': <function Point.__init__ at 0x000000000107A840>, 'add': <function <lambda> at 0x000000000107A6A8>, '__dict__': <attribute '__dict__' of 'Point' objects>}


# print(p1.add(p2)) #Point(14, 26)

#为实例增加方法,未绑定
# if not hasattr(p1, 'sub'):
#     setattr(p1, 'sub', lambda self,other:Point(self.x - other.x, self.y - other.y))
#
# print(p1.sub(p1,p1)) #Point(0, 0)
# print(p1.sub) #<function <lambda> at 0x00000000006AA9D8>
#
# print(p1.__dict__) #{'sub': <function <lambda> at 0x000000000070A9D8>, 'z': 10, 'y': 16, 'x': 4}
# print(Point.__dict__) #{'__module__': '__main__', '__init__': <function Point.__init__ at 0x000000000070A840>, 'add': <function <lambda> at 0x000000000070A6A8>, '__str__': <function Point.__str__ at 0x000000000070A8C8>, '__dict__': <attribute '__dict__' of 'Point' objects>, '__weakref__': <attribute '__weakref__' of 'Point' objects>, '__doc__': None, 'show': <function Point.show at 0x000000000070A950>}
#print(Point.sub) #AttributeError: type object 'Point' has no attribute 'sub'





from functools import partial
#partial用法:将所作用的函数作为partial()函数的第一个参数,原函数的各个参数依次作为partial()函数的后续参数,原函数有关键字参数的一定要带上关键字,没有的话,按原有参数顺序进行补充。
#简单的说就是作用在原函数上,通过参数顺序填充,得到一个新函数
#例如一个非常简单的例子
# max1 = partial(max,5)
# print(max(1,3,6)) #打印结果是6

class ClassMethod:
    def __init__(self, fn):
        self._fn = fn

    def __get__(self, instance, owner):
        ret = partial(self._fn, owner) #为了方便这里的owner可以改成cls,但是上面的也要改,就是instance后面的
        return ret

class A:
    @ClassMethod #等价式:
    def clsmtd(cls):
        print(cls.__name__)
print(A.__dict__)

print(A.clsmtd) #<function A.clsmtd at 0x0000000001134488>
print(A.clsmtd())




class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y


    def __str__(self):
        return ("{},{}".format(self.x, self.y))

    def show(self):
        print("{}, {}".format(self.x ,self.y))

p = Point(4,5)

setattr(Point,'z', 8) #setattr(object,name,value):object的属性存在,则覆盖,不存在,新增
# print(Point.__dict__)
print(hasattr(Point, 'z')) # True   hasattr(object,name):判断对象是否有这个名字的属性,name必须为字符串
print(p.__dict__) #{'x': 4, 'y': 5}
print(Point.__dict__) #{'__module__': '__main__', '__weakref__': <attribute '__weakref__' of 'Point' objects>, '__doc__': None, 'show': <function Point.show at 0x000000000108A950>, '__dict__': <attribute '__dict__' of 'Point' objects>, '__str__': <function Point.__str__ at 0x000000000108A8C8>, '__init__': <function Point.__init__ at 0x000000000108A840>, 'z': 8}
print(getattr(Point,'z')) #8 getattr(object, name[,default])通过name返回object的属性值,当属性不存在,将使用default返回,如果没有default,则抛出AttributeError。name必须为字符串



class A:
    def __init__(self):
        self.a1 = 'a1'
        print('A.init')

class B:
    x = A()
    def __init__(self):  #没有实例化是不会执行的
        # self.b1 = 'b1'
        print('B.init')
# print(B.x.a1)
b = B()
print(b.x.a1)
##类B的x属性是类A的实例,所以类A先实例化,先打印A.init
## 然后执行到打印B.x.a1
##然后实例化并初始化B的实例b
##打印b.x.a1会查找类属性b.x,指向A的实例,所以返回A的实例的属性a1的值



class A:
    def __init__(self):
        self.a1 = 'a1'
        print('A.init')

    def __get__(self, instance, owner):
        print("A.__get__ {} {} {}".format(self, instance, owner))

class B:
    x = A()
    def __init__(self):
        print('B.init')

# print(B.x) #打印结果,A.init,A.__get__ <__main__.A object at 0x00000000010A5550> None <class '__main__.B'>,None
# print(B.x.a1) #AttributeError: 'NoneType' object has no attribute 'a1',看上面的打印结果就是None,因为__get__没有返回值,就相当于return一个None
b = B()
# print(b.x) #A.init,B.init,A.__get__ <__main__.A object at 0x0000000001095550> <__main__.B object at 0x0000000001095588> <class '__main__.B'>,None
# print(b.x.a1) #AttributeError: 'NoneType' object has no attribute 'a1'
print(B.x.a1) #AttributeError: 'NoneType' object has no attribute 'a1', 道理都一样,因为上面没有return值,所以跟一个None要a1,自然要不到

#定义了__get__方法,类A就是一个描述器,对类B或者类B的实例的x属性读取,成为对类A的实例的访问,就会调用__get__方法


class A:
    def __init__(self):
        self.a1 = 'a1'
        print('A.init')

    def __get__(self, instance, owner):
        print("A.__get__ {} {} {}".format(self, instance, owner))
        return self

class B:
    x = A()
    def __init__(self):
        print('B.init')
        self.x = 'b.x' #增加实例属性x

print(B.x) #A.init , A.__get__ <__main__.A object at 0x0000000000BE5518> None <class '__main__.B'> , <__main__.A object at 0x0000000000BE5518>
print(B.x.a1) #调用了get方法:A.__get__ <__main__.A object at 0x0000000001095518> None <class '__main__.B'> ,打印结果为:a1

b = B()
print(b.x) #B.init , b.x
# print(b.x.a1) # AttributeError: 'str' object has no attribute 'a1'
#b.x访问到了实例的属性,但不是描述器



class Base:
    n = 0

class Point(Base):
    z = 6
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def show(self):
        print(self.x, self.y)

    def __getattr__(self, item):
        return "missing {}".format(item)

    def __setattr__(self, key, value):
        print("setattr {}={}".format(key, value))
p1 = Point(5,8)
#setattr(object, name, value):object的属性存在,则覆盖,不存在新增
#__setattr__:通过.访问实例属性,进行增加、修改都要调用它
# __getattr__()通过搜索实例、实例的类及祖先类查不到属性,就会调用此方法
# print(p1.x) # setattr x=5     setattr y=8     missing x
# print(p1.z) #6
# print(p1.n) #0
# print(p1.t) #missing t
# print(p1.__dict__) #{}
# print('########',Point.__dict__)
p1.x = 50 #setattr x=50
# print(p1.__dict__) #{}
p1.__dict__['x'] = 60
print(p1.__dict__) #{'x': 60}
print(p1.x) #60
# print(Point.__dict__)
#实例中通过.点设置属性,如同self.x = x,就会调用__setattr__(),属性要加到实例的__dict__中



class A:
    def __init__(self):
        self.a1 = 'a1'
        print('A.init')

    def __get__(self, instance, owner):
        print("A.__get__ {} {} {}".format(self, instance, owner))
        return self

    def __set__(self, instance, value):
        print('A.__set__ {} {} {}'.format(self, instance, value))
        self.data = value

class B:
    x = A()
    def __init__(self):
        print('B.init')
        self.x = 'b.x' #增加实例属性x
print(B.x) #A.init , A.__get__ <__main__.A object at 0x0000000001095518> None <class '__main__.B'> , <__main__.A object at 0x0000000001095518>
print(B.x.a1) #A.__get__ <__main__.A object at 0x00000000010C5518> None <class '__main__.B'> , a1 发现会调用get方法

print('='*100)
b = B()
print(b.x) #B.init , A.__set__ <__main__.A object at 0x00000000010955F8> <__main__.B object at 0x00000000010956A0> b.x , A.__get__ <__main__.A object at 0x00000000010955F8> <__main__.B object at 0x00000000010956A0> <class '__main__.B'> , <__main__.A object at 0x00000000010955F8>
print(b.x.a1) #A.__get__ <__main__.A object at 0x00000000007855F8> <__main__.B object at 0x00000000007856A0> <class '__main__.B'> , a1 访问到了描述器








#getattr(object, name [,default]):通过name返回object的属性值,不存在,默认default,没有default,抛异常
#setattr(object, name, value):object属性存在,覆盖;不存在,新增
#hasattr(object, name):判断对象是否存在name的属性,name必须为字符串

class Point:
    def __init__(self, x, y):
        self.x = x
        self.y = y

    def __str__(self):
        return 'Point({}, {})'.format(self.x, self.y)


    def show(self):
        # print(self.x, self.y)
        return self

p1 = Point(5,6)
# print(p1) #Point(5, 6)
# print(p1.__dict__) #{'y': 6, 'x': 5}
p2 = Point(6,3)
# print(p2) #Point(6, 3)
# print(p2.__dict__) #{'x': 6, 'y': 3}
# print(repr(p1), repr(p2)) #<__main__.Point object at 0x000000000109E9E8> <__main__.Point object at 0x00000000010A5588> 两个实例

# setattr(p1, 'y', 30)
# print(p1) #Point(5, 30)
# setattr(p1, 'z', 100)
# print(p1) #Point(5, 30)
# print(p1.__dict__) #{'y': 30, 'x': 5, 'z': 100}

#动态调用方法
# if hasattr(p1, 'show'):
#     getattr(p1, 'show')()
#

#动态增加方法
#为类增加方法
# if not hasattr(Point, 'add'):
#     setattr(Point, 'add', lambda self,other:Point(self.x + other.x, self.y + other.y))
# print(Point.add) #<function <lambda> at 0x0000000000B6A6A8>
# print(p1.add) #<bound method <lambda> of <__main__.Point object at 0x0000000000775668>>
# print(p1.add(p2)) #Point(11, 9) #绑定,意思就是出现了bound


#为实例增加方法,未绑定,就是没有出现过bound
if not hasattr(p1, 'sub'):
    setattr(p1, 'sub', lambda self,other:Point(self.x - other.x, self.y - other.y))
print(p1.sub(p1,p1)) #Point(0, 0)
print(p1.sub) #<function <lambda> at 0x00000000010AA6A8>

#动态增删属性的方式是运行时改变类或者实例的方式,但是装饰器或Mixin都是定义时就决定了,因此反射能力具有更大的灵活性。




class Point:
    def __init__(self, x, y): #如果多个参数可以修改成def __init__(self, *args)  self_arg = args
        self.x = x
        self.y = y

    def __str__(self):
        return "Point({} ,{})".format(self.x, self.y)


    def show(self):
        print(self.x, self.y)
        # return self

p1 = Point(8,9)
# print(p1) #Point(8 ,9)
# print(p1.__dict__) #{'y': 9, 'x': 8}
# print(p1.__dict__['y']) #9

p1.z = 1000
# print(p1.__dict__)  #{'x': 8, 'y': 9, 'z': 1000}

# print(dir(p1))     #['__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'show', 'x', 'y', 'z']  #'show', 'x', 'y', 'z'
print(p1.__dir__())  #['__lt__', '__setattr__', '__format__', 'y', '__repr__', '__reduce_ex__', '__le__', '__gt__', '__ge__', '__delattr__', '__dir__', '__hash__', '__reduce__', '__subclasshook__', '__new__', '__eq__', '__doc__', '__module__', 'show', 'z', '__getattribute__', '__weakref__', '__sizeof__', '__str__', '__init__', '__ne__', 'x', '__dict__', '__class__']




本文来自投稿,不代表Linux运维部落立场,如若转载,请注明出处:http://www.178linux.com/88656

(0)
泰谷子泰谷子
上一篇 2017-11-19
下一篇 2017-11-19

相关推荐

  • Python之入门篇

    一、环境准备 环境准备 –> pyenv (安装python解释器,管理Python版本,管理python虚拟环境) https://github.com/pyenv/pyenv https://github.com/yyuu/pyenv-installer # yum -y install git # curl -L https://ra…

    Linux干货 2017-02-05
  • 网络模型知识点概括

       网络模型分层 应用层 网络进程访问表示层 数据表示会话层 主机间通信传输层 端到端连接网络层 数据传输   数据链路层 访问介质物理层 物理线缆二进制封包与解封从下至上封包加包头通过上层协议传给对方机器,对方机器接受后需要从上至下拆解包头,这个过程叫解封三种通讯模式单播广播组播局域网:由服务器-》交换机-》pc …

    Linux干货 2017-05-02
  • N25-第二周作业

    第二周作业 1.Linux上的文件管理命令都有哪些,其常用的使用方法及相关示例演示。 Linux上的文件管理命令有:cp , mv , rm 等命令 cp是复制命令: 命令使用格式是: cp [OPTION]… SOURCE… DEST 例:root@vps ~]# cp /etc/passwd /tmp 复制…

    Linux干货 2016-12-14
  • 磁盘管理的补充及扩展

    磁盘管理的补充及扩展 挂载点和/etc/fstab(配置文件) 使用mount命令挂载为临时挂载开机重启后就会自动卸载,为了永久挂载必须写在配置文件中! 配置文件系统体系  被mount、fsck和其它程序使用  系统重启时保留文件系统体系  可以在设备栏使用文件系统卷标  使用mount  -a 命令挂载/etc/fstab中的所有文件系…

    Linux干货 2016-08-30
  • Linux发行版、发行版联系与区别

    参考这篇文章<2016年最佳Linux发行版排行榜> http://mt.sohu.com/20160128/n436204298.shtml #1 最好的回归发行版:OpenSUSE OpenSUSE背后的SUSE公司是最古老的Linux企业,成立于Linus Torvalds放出Linux的一年之后。它其实早于Red Hat诞生,同时也是社区…

    Linux干货 2016-08-15
  • CentOS 6.5下OpenVPN的搭建

    一、openvpn原理 二、安装openvpn 三、制作相关证书     3.1 制作CA证书     3.2 制作Server端证书     3.3 制作Client端证书 四、配置Server端 五、配置Client端 一、openvp…

    Linux干货 2016-04-21