day16-面向對象基礎(三)

今日摘要函數

今天主要整理一下這倆天學習的內容,面向對象也快學完了,深入的認識到面向對象就是一個思想,怎麼把思想理解了,其餘也就不是什麼事了工具

1.類的約束學習

2.類的類方法與靜態方法spa

3.類的反射code

4.類的內置方法以及雙下方法orm

 

開始今日份總結對象

 

1.類的約束blog

類的約束,就是對類進行一些正確的引導,約束,統一規範,知足正確的開發方式接口

  1.1類的約束的第一種方式ip

class A:
    def pay(self,money):#規定都必須有pay方法
        raise Exception('未定義指定函數')

class Alipay(A):
    def pay(self,money):
        print('本次消費%s'%money)

class JDpay(A):
    def pay(self,money):
        print('本次消費%s'%money)

class Wechatpay(A):
    def zhifu(self,money):
        print('本次消費%s'%money)

w1 = Wechatpay()

def pay(obj,money):#約束一下,約定全部人的支付必須是使用統一的接口,可是這樣也沒又很強烈的約束功能
    obj.pay(money)

pay(w1,100)
#這種事若是沒有定義指定的方法會拋出錯誤

  1.2類的約束的第二種方式

from abc import ABCMeta,abstractmethod
class A(metaclass=ABCMeta):
    def pay(self,money):
        print('請建立正確的方法')
@abstractmethod
class Alipay(A):
    def pay(self,money):
        print('本次消費%s'%money)
class JDpay(A):
    # def zhifu(self,money):
    #     print('本次消費%s'%money)

    def pay(self, money):
        print('這次消費%s' % money)
def pay(obj,money):
    obj.pay(money)
j1 = JDpay()
pay(j1,100)
#第二種方式就是調用abc模塊,可是這種在平常使用中,不多用到,通常都是用第一種。

2.綁定方法與非綁定方法

在類內部通常包含倆種方法,一種爲綁定方法,一種爲非綁定方法

  2.1綁定方法

綁定方法:綁定給誰,就由誰來執行,誰用就會把調用者當作第一個方法傳入

綁定給對象的方法:類內沒有被任何裝飾器修飾的方法

綁定給類的方法:類內定義的裝飾器裝飾的classmethod修飾的方法

看了一圈以及源碼對於怎麼用,或者是使用場景都沒有說,真的是一頭霧水,寫一點本身能理解的把

#本來
class Test_time():
    def __init__(self,year,month,day):
        self.year = year
        self.month = month
        self.day = day

    def out_data(self):
        print('如今日期爲{}年{}月{}日'.format(self.year,self.month,self.day))


t1 = Test_time(2018,12,28)
t1.out_data()
若是傳入數據爲不是正確的數據,例如‘2018-12-28’,就須要其餘函數對數據進行整理


class Test_time():
    def __init__(self,year,month,day):
        self.year = year
        self.month = month
        self.day = day

    def out_data(self):
        print('如今日期爲{}年{}月{}日'.format(self.year,self.month,self.day))

    @classmethod
    def data_solite(cls,msg):
        year, month, day = map(int, msg.split('-'))
        ret = cls(year,month,day)
        return ret
msg ='2018-12-28'
t2 =Test_time.data_solite(msg)
t2.out_data()

這樣的好處就是你之後重構類的時候沒必要要修改構造函數,只須要額外添加你要處理的函數,而後使用裝飾符

在個人理解中,類方法就是將一個類在沒有實例化對象以前調用類裏面的方法,或者是先行修改內容,這樣就不須要修改構造函數,至關於重置構造函數。

  2.2非綁定方法

沒有自動傳值這麼一個說法,就是一個普通函數,一個普通的工具,對於對象和類均可以調用。不與類或者對象進行綁定

就是在方法上加@staticmethod

import time

class TimeTest(object):
    def __init__(self, hour, minute, second):
        self.hour = hour
        self.minute = minute
        self.second = second

    @staticmethod
    def showTime():
        return time.strftime("%H:%M:%S", time.localtime())


print(TimeTest.showTime())
t = TimeTest(2, 10, 10)
nowTime = t.showTime()
print(nowTime)
#類與對象均可以調用,使用對應的方法

3.類的反射

類的反射也是類的內置方法,也是一個特別重要的點

  3.1 hasattr 判斷對象或者類是否存在指定的屬性,看代碼以及結果

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

    def talk(self):
        print("%s is talking."%self.name)

p1 = people('alex',18)
print(hasattr(p1,'name'))
print(hasattr(p1,'sex'))

結果
True
False

hasattr判斷完成後,會返回一個布爾值,有就返回True,無就返回False

  3.2getattr 獲取到一個對象或者類的屬性,加()就是執行,看代碼

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

    def talk(self):
        print("%s is talking."%self.name)

p1 = people('alex',18)
print(getattr(p1,'name'))
print(getattr(p1,'sex','man'))
print(getattr(p1,'sex'))

結果
alex
man
  File "D:/PycharmProjects/s2018/day6/test.py", line 13, in <module>
    print(getattr(p1,'sex'))
AttributeError: 'people' object has no attribute 'sex'

對於getattr,若是對象或者是類有輸入的屬性,則,返回正確屬性。無則報錯,若是咱們指定默認值,則返回默認值,在看一下其餘

class people:
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex

    def talk(self):
        print("%s is talking."%self.name)

p1 = people('alex',18,'woman')

getattr(p1,'talk')()#getattr獲取到方法後加()就是執行
print(getattr(p1,'sex','man'))#類內若是對屬性已經確認過,顯示對象已經確認的值,而不顯示默認值

結果
alex is talking.
woman

  3.3setattr 是修改已有的屬性或者是新加一個屬性,看代碼

class people:
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex

    def talk(self):
        print("%s is talking."%self.name)

p1 = people('alex',18,'woman')

print('修改前',p1.age)
setattr(p1,'age',20)
print('修改後',p1.age)
setattr(p1,'country','China')
print(p1.__dict__)

結果
修改前 18
修改後 20
{'country': 'China', 'name': 'alex', 'sex': 'woman', 'age': 20}

  3.4delattr就是對現有的對象或者類的屬性就行刪除,這個比較簡單,看代碼

class people:
    def __init__(self,name,age,sex):
        self.name = name
        self.age = age
        self.sex = sex

    def talk(self):
        print("%s is talking."%self.name)

p1 = people('alex',18,'woman')

print('修改前',p1.__dict__)
delattr(p1,'name')
print('修改後',p1.__dict__)

結果
修改前 {'age': 18, 'name': 'alex', 'sex': 'woman'}
修改後 {'age': 18, 'sex': 'woman'}

  3.5類的反射其餘用法

在說一下在類的反射中其餘用法

#能夠用於反射的方面有實例化對象, 類,其餘py文件 本py文件
# 1.操做類的角度
class A:
    country = 'China'
    area = '深圳'

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

    def func(self):
        print(666)

print(getattr(A,'country'))
print(getattr(A,'area'))
print(getattr(A,'name'))
getattr(A,'func')(23)
print(hasattr(A,'func2'))

# 2.其餘py文件(模塊)
# 不用反射以前:
import attr
print(attr.flag)
ret = attr.func
# print(ret(10))
print(attr.B.name_list)
obj = attr.B('barry','')
# print(obj.name_list)
print(obj.name)
ret = 'B'
# 用反射的方法:
import attr
print(getattr(attr,'flag'))
# 1,找到func 並執行
ret = getattr(attr,'func')
print(ret(10))
#2,找到B類並調用 name_list func函數
b = getattr(attr,'B')
print(b.name_list)

print(getattr(attr.B,'name_list'))
getattr(attr.B,'func')(1)

#3,找到B類實例化對象在找 name,name_list func函數
b = getattr(attr,'B')
obj = b('alex','')
print(obj.name)
print(obj.name_list)

# 4,本模塊的反射
import sys
obj = sys.modules[__name__]
print(obj)
def func():
    print(666)

ret = input('>>>')
# ret()
getattr(obj,ret)()

def func1():
    print('in func1')

def func2():
    print('in func2')

def func3():
    print('in func3')

l1 = [func1,func2,func3]
for i in l1:
    i()
import sys
obj = sys.modules[__name__]
l1 = ['func%s' % i for i in range(1,4)]
# print(l1)
for i in l1:
    getattr(obj,i)()

到底什麼對象能夠反射

  • 實例化對象
  • 其餘模塊
  • 本模塊(對於本模塊,須要建立sys文件進行設定,若是本模塊中包含模塊則不須要)

4.類的內置方法以及雙下方法

類的內置方法其實包含類的反射中四個方法,上面已經寫了就不在描述

  4.1其餘內置方法

# isinstance 判斷此對象是否是該類(或者是該類的子類)實例化的對象
class A: pass

class B(A): pass

obj = B()
s1 = 'afds'
print(isinstance(obj,B))  #True
print(isinstance(obj,A))  #True
print(isinstance(s1,str))  #True

# issubclass 判斷的是此類是否是後面類的派生類
class D: pass

class A(D): pass

class B(A): pass

abj = B()

print(issubclass(B,A)) #True
print(issubclass(B,D)) #True

  4.2雙下方法

# 特殊雙下方法
# __init__
# len
# s1 = 'fdsafdsa'
# l1 = [1,2,3]
# dic = {'name':'alex','age': 12}
# i = 12
# # print(len(s1))
# int
# # print(len(l1))
# list
# print(len(dic))
# print(len(i))

#
# class A:
# #     def __init__(self,name,age):
# #         self.name = name
# #         self.age = age
# #         self.sex = '男'
# #
# #     def __len__(self):
# #         # print(666)
# #         return len(self.__dict__)
# # a = A('barry', 18)
# # # len(a)  # len(對象) 若是此類中有__len__ 就_方法會自動執行__len_
# # print(len(a))
# print(hash('fsdaf'))
# class A:
#     def __init__(self,name,age):
#         self.name = name
#         self.age = age
#         self.sex = '男'
#
#     def __len__(self):
#         # print(666)
#         return len(self.__dict__)
#
#     def __hash__(self):
#         return 1

    # def __str__(self):
    #     print(555)
    #     return 'fdsaf'

# object
# a = A('barry', 18)
# print(hash(a))
# print(a)  # 對一個對象打印時,自動觸發類中的__str__方法
# print(a,type(a))

# __call__方法
# class Foo:
#
#     def __init__(self):
#         print(11)
#
#     def __call__(self, *args, **kwargs):
#         pass


# obj = Foo()
# obj()  # 對象() 觸發 __call__方法


# __new__ 構造方法

# class A:
    # def __init__(self,name):
    #     self.name = name
    #     print('in A __init__')

# object
# obj = A('alex')

# object
# class A:
#     def __init__(self,name):
#         self.name = name
#         print('in A __init__')
#     def __new__(cls, *args, **kwargs):
#         print('in A __new__')
#         return object.__new__(cls)
#
# a = A('春哥')
# print(a.name)
# 1, 類名() 執行object.__new__方法,開闢的對象空間並返回
# 2,自動執行__init__方法,將空間創給self
# 3,在__init__給對象封裝屬性。

__call__的三件事

  1. 先造一個空對象obj:obj = object.__new__(self)
  2. 初始化obj:self.__init__(obj,*args,**kwargs)
  3. 返回obj:return obj

單例模式,比較重要!

class A:
    __instance = None
    def __init__(self,name,age):
        self.name =name
        self.age = age
    def __new__(cls, *args, **kwargs):
        if cls.__instance is None:
            obj = object.__new__(cls)
            cls.__instance = obj
        return cls.__instance

ret1 = A('alex',123)
ret2 = A('wusir',22)
ret3 = A('barry',18)
print(ret1)
print(ret2)
print(ret3)
#結果
<__main__.A object at 0x01702470>
<__main__.A object at 0x01702470>
<__main__.A object at 0x01702470>
#就會發現單例模式就是不管怎麼實例化,生成的都是同一個,這樣節省名稱空間
相關文章
相關標籤/搜索