1. 程式人生 > >python學習(十七)——補充內建函式、使用迭代器協議實現斐波那契數列、描述符、pycharm的問題

python學習(十七)——補充內建函式、使用迭代器協議實現斐波那契數列、描述符、pycharm的問題

一、補充內建函式

#--------------------------isinstance/isinbclass--------------
class Foo:
    pass

class Bar(Foo):
    pass

b1=Bar()
print(isinstance(b1,Bar))  # b1是否是Bar類
print(isinbclass(Bar,Foo)) # Bar是否繼承Foo
print(type(b1))


#------------------------__getattr__/__getattribute__-----------------
class Foo:
    def __init__(self,x):
        self.x=x

    def __getattr__(self, item):
        print('執行的是getattr')
        return self.__dict__[item]

    def __getattribute__(self, item): # 一定觸發
        print('執行的是getattribute')
        raise AttributeError('丟擲異常了') # 丟擲異常,觸發__getattr__
        # raise TabError('xxxxxx')
f1=Foo(10)
# f1.x
f1.xxxxxx  # 不存在的屬性訪問,觸發__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


#-----------------------------str------------------------------------
class Foo:
    def __init__(self,name,age):
        self.name=name
        self.age=age
    def __str__(self):
        return '名字是%s 年齡是%s' %(self.name,self.age)

f1=Foo('egon',18)
print(f1)            # str(f1)--->f1.__str__()


#-------------------__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__()


#--------------------------自定製format---------------------
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'))

#-------------------------------slots------------------------------
'''
字典會佔用大量記憶體,如果有一個屬性很少的類,但是有很多例項,為了節省空間可以使用該方法
'''
class Foo:
    __slots__=['name','age']  #{'name':None,'age':None}
    # __slots__='name' #{'name':None,'age':None}

f1=Foo()
# f1.name='egon'
# print(f1.name)

# f1.age=18  #--->setattr----->f1.__dict__['age']=18

# print(f1.__dict__)
print(Foo.__slots__)
print(f1.__slots__)
f1.name='egon'
f1.age=17
print(f1.name)
print(f1.age)
# f1.gender='male'


f2=Foo()
print(f2.__slots__)
f2.name='alex'
f2.age=18
print(f2.name)
print(f2.age)


#-----------------------__doc__---------------------------
'''
檢視文件資訊
'''
class Foo:
    '我是描述資訊'
    pass

class Bar(Foo):
    pass
# print(Bar.__doc__) #該屬性無法繼承給子類

# print(Bar.__doc__) #該屬性無法繼承給子類



#------------------------__module__/__class__--------------

from lib.aa import C
c1=C()
print(c1.name)

print(c1.__module__)
print(c1.__class__)

#----------------------__del__-----------------------------
# 一般無需定義,析構方法-當物件在記憶體中被釋放時,自動觸發執行
class Foo:
    def __init__(self,name):
        self.name=name
    def __del__(self):
        print('我執行啦')

f1=Foo('alex')

# del f1    #刪除例項會觸發__del__
del f1.name #刪除例項的屬性不會觸發__del__
print('--------------------->')

# 程式執行完畢會自動回收記憶體,觸發__del__


#--------------------------------__call__----------------
'''
物件後面加括號執行
'''
class Foo:
    def __call__(self, *args, **kwargs):
        print('例項執行啦 obj()')

f1=Foo()

f1() #f1的類Foo 下的__call__
Foo() #Foo的類 xxx下的__call__


#-----------------------------__next__和__iter__實現迭代器協議--------
# 實現迭代
class Foo:
    def __init__(self,n):
        self.n=n
    def __iter__(self):
        return self

    def __next__(self):
        if self.n == 13:
            raise StopIteration('終止了')
        self.n+=1
        return self.n


for i in f1:  # obj=iter(f1)------------>f1.__iter__()
     print(i)  #obj.__next_()

二、使用迭代器協議實現斐波那契數列

class Fib:
    def __init__(self):
        self._a=1
        self._b=1

    def __iter__(self):
        return self
    def __next__(self):
        if self._a > 100:
            raise StopIteration('終止了')
        self._a,self._b=self._b,self._a + self._b
        return self._a

f1=Fib()
print(next(f1))
print(next(f1))
print(next(f1))
print(next(f1))
print(next(f1))
print('==================================')
for i in f1:
    print(i)

三、描述符

1、描述符

class Foo:
    def __get__(self, instance, owner):
        print('===>get方法')
    def __set__(self, instance, value):
        print('===>set方法',instance,value)
        instance.__dict__['x']=value #b1.__dict__
    def __delete__(self, instance):
        print('===>delete方法')


class Bar:
    x=Foo() #在何地?
    def __init__(self,n):
        self.x=n #b1.x=10
b1=Bar(10)
print(b1.__dict__)
b1.x=11111111111111111
print(b1.__dict__)

b1.y=11111111111111111111111111111111111111
print(b1.__dict__)

2、注意事項

'''
1、描述符本身應該定義成新式類,被代理的類也應該是新式類
2、必須把描述符定義成這個類的類屬性,不能定義到解構函式中
3、要嚴格遵循優先順序,如下
   類屬性 > 資料描述符 > 例項屬性 > 非資料描述符 > 找不到的屬性__getattr__
'''

四、軟體開發規範

'''
 program
|--bin
|--conf
|--db
|--lib
|--log
|--src

'''

五、pycharm的問題

import sys,os
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
sys.path.append(BASE_DIR)

from bin import start  # bin/start.py

'''
尋找路徑:
# 當前目錄
# sys.path 環境變數

pycharm自動把當前專案新增到環境變數中
'''
 index.say_hi()