溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

python學習之面向?qū)ο蟾呒壧匦院湍g(shù)方法

發(fā)布時間:2020-07-25 10:55:31 來源:網(wǎng)絡 閱讀:357 作者:霍金181 欄目:編程語言

01_property商品應用.py

分頁顯示是一種非常常見的瀏覽和顯示大量數(shù)據(jù)的方法,屬于web編程中最常處理的事件之一。

類屬性應用需求: 對于京東商城中顯示電腦主機的列表頁面,每次請求不可能把數(shù)據(jù)庫
中的所有內(nèi)容都顯示到頁面上,而是通過分頁的功能局部顯示,所以在向數(shù)據(jù)庫中請求
數(shù)據(jù)時就要顯示的指定獲取從第start條到第end條的所有數(shù)據(jù) 這個分頁的功能包括:
? 根據(jù)用戶請求的當前頁和總數(shù)據(jù)條數(shù)計算出 start 和 end
? 根據(jù)start 和 end 去數(shù)據(jù)庫中請求數(shù)據(jù)
? 是否有上一頁has_prev、下一頁has_next
? 上一頁prev、下一頁next
? 總頁數(shù)pages, 數(shù)據(jù)總條數(shù)total、當前頁信息items

"""

class Pagintor(object):
    """實現(xiàn)商品分頁的類"""
    def __init__(self, objects_list, page=1, per_page=5):
        """
        :param objects_list: 商品列表
        :param page: 當前需要顯示的頁碼信息
        :param per_page: 每頁顯示的數(shù)據(jù)個數(shù)
        """
        self.objects_list = objects_list
        self.page = page
        self.per_page = per_page

    @property
    def start(self):
        return (self.page - 1) * self.per_page

    @property
    def end(self):
        return self.page * self.per_page

    @property
    def total(self):
        """
        數(shù)據(jù)總條數(shù)total
        :return:
        """
        return len(self.objects_list)

    @property
    def pages(self):
        """
        總頁數(shù)pages
        if 總商品數(shù)量%每頁顯示數(shù)量==0:  剛好當前頁顯示滿
        else: 好友多與的部分, 在計算的結(jié)果上面加1
        self.total = 5  pages=1
        self.total = 6  pages=2
        :return:
        """
        result = self.total // self.per_page
        if self.total % self.per_page == 0:
            return result
        else:
            return result + 1

    @property
    def has_next(self):
        return True if 0 < self.page + 1 <= self.pages else False

    @property
    def next(self):
        next_page = self.page - 1
        next_start = (next_page - 1) * self.per_page
        next_end = self.page * self.per_page
        return self.objects_list[next_start:next_end]

    @property
    def has_prev(self):
        return True if 0 < self.page - 1 <= self.pages else False

    @property
    def prev(self):
        prev_page = self.page - 1
        prev_start = (prev_page - 1) * self.per_page
        prev_end = self.page * self.per_page
        return self.objects_list[prev_start:prev_end]

    @property
    def items(self):
        """
        當前頁信息items
        :return:
        """
        return self.objects_list[self.start:self.end]

if __name__ == '__main__':
    # 應用場景二: 某一個屬性不能直接返回, 需要計算的, 可以通過property屬性實現(xiàn)
    goods = ["電腦" + str(i) for i in range(5)]
    #需求: 顯示第三頁時, 開始的索引是? 結(jié)束的索引為多少?
    pagintor = Pagintor(goods, page=1, per_page=6)
    print("第1頁的商品信息為: ", goods[pagintor.start:pagintor.end])
    print("是否有上一頁?", pagintor.has_prev)
    print("總頁數(shù)?", pagintor.pages)
"""

02_property通過函數(shù)的方式實現(xiàn)類屬性.py

class Person(object):
    def __init__(self, name, age):
        self.name = name
        self.__age = age  #私有屬性

    @property
    def is_age_vaild(self):
        return  0 < self.__age <= 150
    def get_age(self):
        if self.is_age_vaild:
            return self.__age
        else:
            raise Exception("年齡不合法")

    def set_age(self, age):
        if self.is_age_vaild:
            self.__age = age
        else:
            raise Exception("年齡不合法")

    def del_age(self):
        print("年齡屬性刪除......")
    #類屬性 即:在類中定義值為property對象的類屬性
    age = property(fget=get_age, fset=set_age, fdel=del_age)

if __name__ == '__main__':
    p1 = Person("張三", 30)
    print(p1.age)
    p1.age = 31
    print(p1.age)
    del p1.age

03_property通過函數(shù)的方式實現(xiàn)類屬性.py

class Person(object):
    def __init__(self, name, age, score):
        self.name = name
        self.__age = age  # 私有屬性
        self.__score = score

    @property
    def score(self):
        return  self.__score
    @score.setter
    def score(self, score):
        self.__score = score

    @property
    def is_age_vaild(self):
        return  0 < self.__age <= 150

    @property           # 獲取age屬性時執(zhí)行的內(nèi)容
    def age(self):
        if self.is_age_vaild:
            return self.__age
        else:
            raise Exception("年齡不合法")
    @age.setter         # 設置age屬性時執(zhí)行的內(nèi)容
    def age(self, age):
        if self.is_age_vaild:
            self.__age = age
        else:
            raise Exception("年齡不合法")
    @age.deleter        # 刪除age屬性時執(zhí)行的內(nèi)容
    def age(self):
        print("年齡屬性刪除......")

if __name__ == '__main__':
    p1 = Person("張三", 30, 100)
    print(p1.age)       # 獲取年齡(), 執(zhí)行@property def age(self):
    p1.age = 31         # 設置年齡, age=31
    print(p1.age)
    del p1.age          # 刪除年齡屬性

05_裝飾器實現(xiàn)單例模式.py

from functools import wraps
def singleton(cls):
    """
    實現(xiàn)單例模式的裝飾器
    思路: 當實例化對象時, 判斷該類是否實例化過對象。
    - 如果是, 返回之前實例化的對象。
    - 如果不是, 實例化第一個對象, 并將實例化后的對象存儲起來(緩存)。
    """
    instances = {}  # {'Person': obj}

    @wraps(cls)
    def wrapper(*args, **kwargs):
        name = cls.__name__
        if instances.get(name):
            # 直接返回緩存中的對象
            return instances.get(name)
        else:
            # 第一次實例化對象
            obj = cls(*args, **kwargs)
            #類名作為key值, 對象作為value值, 存儲到instances字典中.
            instances[name] = obj
            return obj

    return wrapper

@singleton
class Person(object):
    pass

if __name__ == '__main__':
    p1 = Person()
    p2 = Person()
    #面試題目: ==和is有什么區(qū)別?
    print("單例模式是否成功?", p1 is p2)

魔術(shù)方法
在Python中,所有用""包起來的方法,都稱為【魔術(shù)方法】(eg: len, init__)。
魔術(shù)方法一般是為了讓顯示器調(diào)用的,你自己并不需要調(diào)用它們。
特殊屬性:
python學習之面向?qū)ο蟾呒壧匦院湍g(shù)方法
dir
查看屬性
返回類或者對象的所有成員名稱列表。dir() 函數(shù)就是調(diào)用dir()。
1). 如果dir([obj]) 參數(shù)obj包含方法 dir(),該方法將被調(diào)用。
2). 如果Obj 不包含 dir(),該方法將最大限度收集屬性信息
python 中new , init , call的區(qū)別?
1). new的功能是在生成對象之前執(zhí)行的內(nèi)容,接受的參數(shù)是cls 類, 負責對象的創(chuàng)建
2). init的功能是在對象生成之后執(zhí)行的內(nèi)容, 接受的參數(shù)是self 對象, 負責對象的初始化
3). call的功能是在調(diào)用對象時執(zhí)行的內(nèi)容, 可以模擬函數(shù)的行為

06_new方法實現(xiàn)單例模式改進版.py

from datetime import  date

class Person(object):
    def __new__(cls, *args, **kwargs):
        print("判斷當前類是否擁有instance屬性?", hasattr(cls, 'instance'))
        if not hasattr(cls, 'instance'):
            cls.instance = super(Person, cls).__new__(cls)
        return  cls.instance

    def __init__(self, name):
        self.name = name

p1 = Person("張三")
p2 = Person("張xxx")
print("單例模式是否成功? ", p1 is p2)

06_通過new方法實現(xiàn)單例模式.py

class Person(object):
    # 1). 設置類屬性, 存儲已經(jīng)創(chuàng)建好的對象。
    _instance = None
    def __new__(cls, *args, **kwargs):
        print("new方法在實例化對象之前執(zhí)行.....返回對象本身")
        #2). 判斷是否已經(jīng)實例化對象?
        if cls._instance:
            return  cls._instance
        else:
            self = object.__new__(cls)
            cls._instance = self
            #返回父類object的new方法創(chuàng)建的對象.....
            return self

    def __init__(self):
        print("構(gòu)造方法實例化對象之后執(zhí)行......")

if __name__ == '__main__':
    p1 = Person()
    p2 = Person()
    print(p1, p2)"""

07_call.py

1). new的功能是在生成對象之前執(zhí)行的內(nèi)容,接受的參數(shù)是cls 類, 負責對象的創(chuàng)建
2). init的功能是在對象生成之后執(zhí)行的內(nèi)容, 接受的參數(shù)是self 對象, 負責對象的初始化
3). call的功能是在調(diào)用對象時執(zhí)行的內(nèi)容, 可以模擬函數(shù)的行為.
"""

class Person(object):
    def __new__(cls):
        print("__new__")
        return  object.__new__(cls)

    def __init__(self):
        print("__init__")

    def __call__(self, *args, **kwargs):
        print('__call__')

    def __del__(self):
        # 析構(gòu)方法: 當對象被刪除或者從內(nèi)存釋放時自動執(zhí)行
        print("__del__")
p1 = Person()
p1()

08_call魔術(shù)方法實現(xiàn)緩存.py

from functools import  lru_cache

class Fib(object):
    @lru_cache(maxsize=1000)
    def __call__(self, n):
        if n in (1, 2):
            return  1
        else:
            return  self(n-1) + self(n-2)
fib = Fib()
print(fib(100))  # 1 1 2 3 5 8"""

可視化
類型判斷要使用type或isinstance, 不能通過判斷print輸出是否帶引號來判斷輸出值的類型。
1). str()與repr()都是python中的內(nèi)置函數(shù),是直接用來格式化字符串的函數(shù)。
2). 當使用內(nèi)置函數(shù)str(obj)時, 自動執(zhí)行obj.str()魔術(shù)方法。
3). 當使用內(nèi)置函數(shù)repr(obj)時, 自動執(zhí)行obj.repr()魔術(shù)方法。
4). 當str魔術(shù)方法不存在時, 自動執(zhí)行repr()魔術(shù)方法的內(nèi)容。
類型轉(zhuǎn)換
python學習之面向?qū)ο蟾呒壧匦院湍g(shù)方法

09_可視化魔術(shù)方法.py

class Person(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def __int__(self):
        return int(self.age)

    #def __str__(self):
    #return  'Person<%s>' %(self.name)
    def __repr__(self):
        return  'Person<%s>' %(self.name)
p1 = Person("fentiao", '100')
print(p1)
print(int(p1))

索引與切片
拓展小知識: slice() 函數(shù)實現(xiàn)切片對象,主要用在切片操作函數(shù)里的參數(shù)傳遞。
索引&切片魔術(shù)方法:
setitem:當屬性被以索引、切片方式賦值的時候會調(diào)用該方法
getitem:一般如果想使用索引、切片訪問元素時,就可以在類中定義這個方法
delitem:當使用索引、切片刪除屬性時調(diào)用該方法

10_魔術(shù)方法實現(xiàn)索引和切片.py

class Student(object):
    def __init__(self, name, scores):
        self.name = name
        self.scores = scores

    def __getitem__(self, index):
        """實現(xiàn)獲取索引和切片值的魔術(shù)方法"""
        print(index)
        return self.scores[index]
    def __setitem__(self, index, value):
        """實現(xiàn)修改/設置索引和切片值的魔術(shù)方法"""
        self.scores[index] = value
    def __delitem__(self, index):
        del self.scores[index]

    def __mul__(self, other):
        """重復操作"""
        return  self.scores * other

    def __add__(self, other):
        """連接操作, 傳入的時對象"""
        return [ item[0]+item[1] for item in zip(self.scores, other.scores)]

    def __contains__(self, item):
        """成員操作符"""
        return  item in self.scores

    def __iter__(self):
        # iter可以將可迭代對象轉(zhuǎn)換成迭代器(可以調(diào)用next方法的)
        return  iter(self.scores)

stu1 = Student("張三", [100, 90, 100])
stu2 = Student("里斯", [100, 80, 100])

#1). 索引和切片的測試
#print(stu1[1:])             # 獲取索引/切片值
#stu1[1:] = (80, 80)        # 設置索引/切片對應的value值
#print(stu1.scores)
#del stu1[1:]                # 刪除索引/切片值
#print(stu1.scores)

##2). 連接、重復和成員操作符
#print(stu1*3)
#print(stu1 + stu2)
#print(150 in stu1)

for item in stu1:
    print(item)

with語句安全上下文
with語句操作的對象必須是上下文管理器。那么,到底什么是上下文管理器呢?
1). 簡單的理解,擁有 enter() 和 exit() 方法的對象就是上下文管理器。
enter(self):進入上下文管理器自動調(diào)用的方法,在 with 執(zhí)行之前執(zhí)行。如果 有 as子句,該
方法的返回值被賦值給 as 子句后的變量;該方法可以返回多個值。
exit(self, exc_type, exc_value, exc_traceback):退出上下文管理器自動調(diào)用的方法。在
with 執(zhí)行之后執(zhí)行(不管有無異常)。
2). 當 with as 操作上下文管理器時,就會在執(zhí)行語句體之前,先執(zhí)行上下文管理器的 enter() 方法,
然后再執(zhí)行語句體,最后執(zhí)行 exit() 方法。
構(gòu)建上下文管理器,常見的有 2 種方式:基于類實現(xiàn)和基于生成器實現(xiàn)。
方法一: 裝飾器 contextlib.contextmanager,來定義自己所需的基于生成器的上下文管理器
方法二: 基于類的上下文管理器: 只要一個類實現(xiàn)了 enter() 和 exit() 這 2 個方
法,程序就可以使用 with as 語句來管理它

11_魔術(shù)方法實現(xiàn)with語句上下文管理器.py

class Connect(object):
    def __init__(self, filename):
        self.filename = filename
    def __enter__(self):
        self.f = open(self.filename)
        return  self.f

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('with語句執(zhí)行之后......')
        self.f.close()

#Connect就是上下文管理器。 擁有 __enter__() 和 __exit__() 方法的對象就是上下文管理器
with Connect('/etc/passwd') as conn:
    pass

12_裝飾器實現(xiàn)上下文管理器的方法.py


import  contextlib
import  tempfile
import  shutil

@contextlib.contextmanager
def make_temp_dir():
    try:
        tmp_dir = tempfile.mkdtemp()
        yield  tmp_dir
    finally:
        shutil.rmtree(tmp_dir)
with make_temp_dir() as f:
    pass

13_比較大小.py

class Int(object):
    def __init__(self, number, weight):
        self.number = number
        self.weight = weight

    def __gt__(self, other):
        """判斷大于的魔術(shù)方法"""
        return  self.number * self.weight > other.number * other.weight

    def __ge__(self, other):
        """判斷大于等于的魔術(shù)方法"""
        return  self.number * self.weight >= other.number * other.weight

    def __eq__(self, other):
        """判斷等于的魔術(shù)方法"""
        return self.number * self.weight == other.number * other.weight

i1 = Int(20, 3)
i2 = Int(20, 3)
print(i1 > i2)
print(i1 < i2)
print(i1 >= i2)
print(i1 == i2)
print(i1 != i2)

01_call魔術(shù)方法實現(xiàn)類裝飾器.py

from  functools import  wraps
import time
def timeit(unit='s'):
    def wrapper1(fun):  # fun=add
        @wraps(fun)
        def wrapper(*args, **kwargs):
            if unit == 's':
                start_time = time.time()
                result = fun(*args, **kwargs)       # add(1, 2)  result=3
                end_time = time.time()
                print("%s函數(shù)運行時間為%.2f s" %(fun.__name__, end_time-start_time))
                return  result
            else:
                print("當前功能不支持......")
        return  wrapper
    return  wrapper1

#類裝飾器: 裝飾器需要傳遞的參數(shù)通過__init__傳遞進入.被裝飾函數(shù)執(zhí)行的內(nèi)容在__call__魔術(shù)方法中編寫。
class TimeIt(object):
    def __init__(self, unit='s'):
        self.unit = unit
    def __call__(self,fun):
        @wraps(fun)
        def wrapper(*args, **kwargs):
            if self.unit == 's':
                start_time = time.time()
                result = fun(*args, **kwargs)  #add(1, 2)   result=3
                end_time = time.time()
                print("%s函數(shù)運行時間為%.2f s" % (fun.__name__, end_time - start_time))
                return result
            else:
                print("當前功能不支持......")
        return  wrapper
#@timeit(unit='s')       #@wrapper1 ==> add = wrapper1(add)  ===> add =wrapper
#def add(num1, num2):
#time.sleep(0.333)
#return  num1 + num2

"""
@TimeIt(unit='h') 
#1). TimeIt_obj = TimeIt(unit='h')  
#2). @TimeIt_obj
#3). add=TimeIt_obj(add)
#4). add = wrapper
"""
@TimeIt(unit='s')
def add(num1, num2):
    time.sleep(0.333)
    return  num1 + num2

#add(1, 2)  ==> wrapper(1, 2)
add(1, 2)

02_call魔術(shù)方法實現(xiàn)偏函數(shù).py

from functools import  partial

max_100 = partial(max,10, 100)  # 返回對象
print(max_100(1, 2, 3))   # 100"""

03_基于call魔術(shù)方法和filter實現(xiàn)文件過濾器.py

from wtforms    import  StringField,SubmitField
import os
#作為基類/父類
class FileAcceptor(object):
    def __init__(self, accepted_extensions):
        """
        eg: ['.png', '.jpg']
        :param accepted_extensions: 可以接受的擴展名
        """
        self.accepted_extensions = accepted_extensions

    def __call__(self, filename):
        """
        eg: hello.jpg
        :param filename: 需要判斷的文件名
        :return:
        """
        #base = 'hello', ext='.jpg'
        base, ext = os.path.splitext(filename)
        return  ext in self.accepted_extensions

#子類
class ImageFileAcceptor(FileAcceptor):
    def __init__(self):
        image_ext = ('.jpg', '.jepg', '.png')
        super(ImageFileAcceptor, self).__init__(image_ext)

#子類
class ExcelFileAcceptor(FileAcceptor):
    def __init__(self):
        image_ext = ('.xls', '.xlsx')
        super(ExcelFileAcceptor, self).__init__(image_ext)

if __name__ == '__main__':
    filenames = [
        'hello.jpg',
        'hello.xls',
        'hello.txt'
    ]
    """
    1). ImageFileAcceptor() 實例化對象, 執(zhí)行__new__和__init__魔術(shù)方法。
    2). imagefileacceptor_obj
    3). imagefileacceptor_obj('hello.jpg')  True
    3). imagefileacceptor_obj('hello.xls')  False
    3). imagefileacceptor_obj('hello.txt')  False
    4). ['hello.jpg']

    """
    images_file = filter(ImageFileAcceptor(), filenames)
    excels_file = filter(ExcelFileAcceptor(), filenames)
    print(list(images_file))
    print(list(excels_file))

04_通過分支語句動態(tài)的創(chuàng)建類.py

def create_class(name):
    if name == 'foo':
        class Foo(object):
            pass
        return  Foo
    else:
        class Bar(object):
            pass
        return  Bar

cls = create_class(name='foo1')
print(cls.__name__)

05_通過type動態(tài)地創(chuàng)建類.py

#type函數(shù)語法:
#type(類名, 父類名稱的元組, 屬性信息)
#class Person(object):
#country= 'China'

def hello(self):
    print("hello")
Person = type('Person',(object, ), {'country':'China', 'hello':hello})
p1 = Person()
print(p1.country)
p1.hello()

魔術(shù)方法匯總
基本的魔法方法
有關屬性的魔術(shù)方法
比較操作符
算數(shù)運算符
反運算
增量賦值運算
一元操作符
類型轉(zhuǎn)換
上下文管理(with 語句)
容器類型
python學習之面向?qū)ο蟾呒壧匦院湍g(shù)方法

元類
類也是對象
Python一切皆對象
Linux一切皆文件
元類是類的類,是類的模板
元類的實例為類,正如類的實例為對象。
類的本質(zhì)是對象, 于是可以對類做如下的操作:

  1. 你可以將它賦值給一個變量
  2. 你可以拷?它
  3. 你可以為它增加屬性
  4. 你可以將它作為函數(shù)參數(shù)進行傳遞
    1). 元類就是創(chuàng)建類的類。函數(shù)type就是是元類。
    2). Python中一切皆對象。包括整數(shù)、字符串、函數(shù)以及類都是對象,且都是從type類創(chuàng)建而來。
    3). 動態(tài)生成類,不能控制類是如何生成的。python3 的metaclass可動態(tài)創(chuàng)建類。
    4). 很多Web框架都會使用metaclass 來創(chuàng)建類。掌握元類對理解源代碼至關重要。eg: ORM框架類

    06_metaclass自定義元類.py

    #實現(xiàn)單例模式的方法:
    #1. 裝飾器
    #2. new魔術(shù)方法
    #3. metaclass自定義元類

class Singleton(type):
    type(name, bases, attrs)
    自定義元類實現(xiàn)單例模式, 父類是type
    #所有類和實例化對象之間的關系; eg: {'Person': Pseron()}
    cache = {}

    #1). 為什么是__call__魔術(shù)方法?
    def __call__(cls):
        #判斷類是否已經(jīng)實例化, 如果沒有, 實例化后存儲到緩存中。 最后將緩存的信息返回給用戶。
        if cls not in  cls.cache:
            cls.cache[cls] = super(Singleton, cls).__call__()
        return  cls.cache[cls]

#type('Pseron', (), {})
#創(chuàng)建以各類Person, 指定創(chuàng)建Person類的類(元類)是type.
#2. metaclass是在做什么? 指定元類為Singleton。
class Person(object, metaclass=Singleton):  # Person = Singleton.__new__(Person, (objects, ), {})
    pass

#Person是Singleton元類實例化出的對象, Person()就是對象(), 執(zhí)行Singleton.__call__魔術(shù)方法.
p1 = Person()
p2 = Person()
print(p1, p2)

#99%情況不需要自己自定義元類。

抽象基類
抽象基類有兩個特點:
1.規(guī)定繼承類必須具有抽象基類指定的方法
2.抽象基類無法實例化
基于上述兩個特點,抽象基類主要用于接口設計
實現(xiàn)抽象基類可以使用內(nèi)置的abc模塊

07_抽象基類.py

import abc
class Human(metaclass=abc.ABCMeta):
    """基類, 定義一個抽象類"""
    @abc.abstractmethod
    def introduce(self):
        print("introduce.....")
    @abc.abstractmethod
    def hello(self):
        print('hello')

class Person(Human):
    # 1).規(guī)定繼承類必須具有抽象基類指定的方法
    def introduce(self):
        print('person')
    def hello(self):
        print('person hello')

#2). 抽象基類無法實例化
#h = Human()
p = Person()
p.introduce()
p.hello()

動態(tài)語言與靜態(tài)語言的不同?

  1. 動態(tài)語言:可以在運行的過程中,修改代碼
  2. 靜態(tài)語言:編譯時已經(jīng)確定好代碼,運行過程中不能修改
    slots
    如果我們想要限制實例的屬性怎么辦?
  3. Python允許在定義class的時候,定義一個特殊的slots變量,來限制該class實例能添加的屬性
  4. 使用slots要注意,slots定義的屬性僅對當前類實例起作用,對繼承的子類是不起作用的

    08_slots限制對象屬性.py

import time
from datetime import  date
#d = date.today()
#print("對象類型: ", type(d))        # <class 'datetime.date'>
#print("判斷是否有year這個屬性?", hasattr(d, 'year')) # True
#print("判斷是否有time這個屬性?", hasattr(d, 'time')) # False
##setattr(d, 'time', '10:10:10')  # 報錯
class Date(object):
    # __slots__ 來限制該對象能添加的屬性信息
    __slots__ =  '__year', '__month', '__day'
    def __new__(cls, year, month, day):
        self = object.__new__(cls)
        self.__year = year
        self.__month = month
        self.__day = day
        return  self
    @property
    def year(self):
        return  self.__year

    @property
    def month(self):
        return self.__month

    @property
    def day(self):
        return self.__day
    @classmethod
    def today(cls):
        time_t = time.localtime()
        return  cls(time_t.tm_year, time_t.tm_mon, time_t.tm_mday)

    def __str__(self):
        return  '%s-%s-%s' %(self.__year, self.__month, self.__day)
d = Date(2019, 10, 10)
print("對象類型: ", type(d))        # <class 'datetime.date'>
print("判斷是否有year這個屬性?", hasattr(d, 'year')) # True
print("判斷是否有time這個屬性?", hasattr(d, 'time')) # False
#setattr(d, 'time', '10:10:10')      # Error
#print('time:', getattr(d, 'time'))  # Error

print(Date.today())

09_垃圾回收機制.py

#1). 整數(shù)在程序中的使用非常廣泛,Python為了優(yōu)化速度,使用了小整數(shù)對象池,
#避免為整數(shù)頻繁申請和銷毀內(nèi)存空間。

#2). Python對小整數(shù)的定義是[-5,257)
>>> a = 1
>>> id(a)
139883638752032
>>> b = 1
>>> id(b)
139883638752032
>>> c = 257
>>> d = 257
>>> id(c), id(d)
(139883633580400, 139883633580432)
>>> e=-5;f=-5
>>> id(e), id(f)
(139883638751840, 139883638751840)

#********************************2. 字符串駐留機制 ********************************
#1). string interning(字符串駐留): 它通過維護一個字符串常量池(string intern pool),
#從而試圖只保存唯一的字符串對象,達到既高效又節(jié)省內(nèi)存地處理字符串的目的。
>>> a = 'hello'
>>> b = 'hello'
>>> id(a), id(b)
(139883511138480, 139883511138480)
>>> c = 'pythonchjdshfcejhfkjrehfkjrehfkjrehfregjrkhgkjrg'
>>> d = 'pythonchjdshfcejhfkjrehfkjrehfkjrehfregjrkhgkjrg'
>>> id(c),id(d)
(139883633099360, 139883633099360)

#2). 字符串(含有空格),不可修改,沒開啟intern機制,不共用對象,引用計數(shù)為0,銷毀。
>>> a = 'a b'
>>> b = 'a b'
>>> id(a), id(b)
(139883511138608, 139883511138544)

10_引用計數(shù)機制.py

#導致引用計數(shù)+1的情況
>>> #1). 對象被創(chuàng)建,例如a=23
...
>>> name = 'fentiao'
>>>
>>> #2). 對象被作為參數(shù),傳入到一個函數(shù)中
...
>>> import sys
>>> sys.getrefcount(name)
2
>>> #3). 對象被引用,例如b=a
...
>>> cat_name = name
>>> sys.getrefcount(name)
3
>>> #4). 對象作為一個元素,存儲在容器中,例如list1=[a,a]
...
>>> l = [name, 'hello', 'python']
>>> sys.getrefcount(name)
4

#***************************導致引用計數(shù)-1的情況*************************
>>> #1). 對象的別名被顯式銷毀,例如del a
...
>>> del cat_name
>>> sys.getrefcount(name)
3
>>> #2). 對象的別名被賦予新的對象,例如a=24
>>> name1 = name
>>> sys.getrefcount(name)
4
>>> name1 = 'hello'
>>> sys.getrefcount(name)
3
>>> #4). 對象所在的容器被銷毀,或從容器中刪除對象
...
>>> l
['fentiao', 'hello', 'python']
>>> del l[0]
>>> sys.getrefcount(name)
2

#****************************gc模塊使用***********************************
#1). 分代回收的頻率
>>> gc.get_threshold()
(700, 10, 10)
>>>gc.set_threshold(700, 90, 90)
KeyboardInterrupt

#2). 垃圾回收機制是否開啟
>>>gc.isenabled()
True
>>>gc.disable()
>>>gc.isenabled()
False
>>> gc.enable()
>>>gc.isenabled()
True
向AI問一下細節(jié)
AI