學習總結

課上練習整理

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.www58058.com/88656

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

相關推薦

  • 第一周作業

    作業

    Linux干貨 2018-03-20
  • yum與rpm包

    yum與rpm包 包命名和工具 包:分類和拆包 Application-VERSION-ARCH.rpm:主包 Application-devel-VERSION-ARCH.rpm 開發子包 Application-utils-VERSION-ARHC.rpm 其它子包 Application-libs-VERSION-ARHC.rpm 其它子包 包之間:可…

    Linux干貨 2017-05-08
  • 基于mysql數據庫的日志分析系統

    現如今,日志已經成為了我們分析系統及相關服務的一個重要工具。而日志也具有其相對較為固定的格式以便于進行統計查詢。其大致格式如下: 日期時間            主機      &…

    Linux干貨 2016-10-23
  • 由摩根定律引發的思考

    在Linux中,我們常常需要對一些條件進行判斷,而對于多個條件的組合判斷是基于摩根定律而進行的。所以理解摩根定律對于我們學習條件判斷是很有必要的,下面我們就先介紹摩根定律進而引出其在一些具體場景上的應用。   一、摩根定律 在Linux中的條件判斷中,摩根定律可以以下式來表示: !( A || B )=!A && !B !( A &…

    Linux干貨 2016-08-16
  • Nginx 負載均衡多個nmmp主機

    設計拓撲圖 一、Memcache簡介 cache(緩存系統) 高性能分布式緩存服務器,緩存所有的“可流式化”數據:livejournal旗下Danga Interacive公司 程序=指令+數據 指令:程序 數據:IO操作 文件系統: 特征:協議簡單  基于libevent的事件處理  內置內存存儲方式  memcached 不…

    2014-09-17
  • bash腳本之for循環和while循環及包管理

    一.概述 上一章剩余內容 壓縮工具 cpio 復制從或到文件 cpio命令是通過重定向的方式將文件進行打包備份,還原恢復的工具,它可以解壓以“.cpio”或者“.tar”結尾的文件。 cpio[選項] > 文件名或者設備名 cpio[選項] < 文件名或者設備名 選項 -o 將文件拷貝打包成文件或者將文件輸出到設備上 -i解包,將打包文件解壓或將…

    Linux干貨 2016-08-24
欧美性久久久久