学习总结

课上练习整理

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

相关推荐

  • 构建私有CA

    构建私有CA 我们采用openssl这个软件来实现 所有首先我们来看下该软件的配置文件 实现环境 centos 7.2 [root@redhat7 ~]# rpm -qc openssl  //可以看到该命令没有任何输出,我们可以思考该软件包还存在其他的支包 [root@redhat7 ~…

    Linux干货 2016-09-28
  • 第四周作业

    1、复制/etc/skel目录为/home/tuser1,要求/home/tuser1及其内部文件的属组和其它用户均没有任何访问权限;          [root@yangjifeng~]# cp -a /etc/skel /home/tuser1 [root@yangjife…

    Linux干货 2017-08-28
  • 关于大型网站技术演进的思考(八):存储的瓶颈(8)

    原文出处: 夏天的森林  在开始本篇主要内容前,我们一起看看下面的几张截图,首先是第一张图,如下图所示: 这是一家电商网站的首页,当我们第一次打开这个首页,网站会弹出一个强制性的对话框,让用户选择货物配送的地址,如果是淘宝和京东的话,那么这个选择配货地址的选项是在商品里,如下图是淘宝的选择配送地点: 下图是京东选择配货地点: 那么图一跟京…

    2015-03-11
  • 创建CA、申请证书和吊销证书详解

    创建CA和申请证书、吊销证书 搭建工具:openssl 服务端:centos7 客户端:centos6 配置实验环境: 需要两台虚拟机为服务端、客户端提供运行环境,装载openssl工具,添加必要文件;通过查看openssl的配置文件/etc/pki/tls/openssl.cnf(图一),对比服务端的/etc/pki/CA文件内容(图二),如果第一次搭建服…

    2017-04-11
  • gawk基础

     一、gawk 是什么 在了解gawk之前,先了解一下文本三工具      文本过滤工具:grep|egrep|fgrep   其中fgrep不支持正则表达式 1.行编辑器:sed      sed 有两种空间   模式空间    保持空间 2. 文…

    Linux干货 2016-06-24
  • Linux系统重定向和管道

    1、标准输入和标准输出              程序:指令+数据               &n…

    Linux干货 2016-08-04