Python基礎:一塊兒來面向對象 (一)

類,一羣有着相同屬性和函數的對象的集合

  若是你不知足於只作一個+CRUD「碼農」,而是想成爲一個優秀的工程師,那就必定要積極鍛鍊直覺思考和快速類比的能力,其是在找不到bug的時候
  
  類的示例:
class Document():
    def __init__(self, title, author, context):
        print('init function called')
        self.title = title
        self.author = author
        self.__context = context # __ 開頭的屬性是私有屬性

    def get_context_length(self):
        return len(self.__context)

    def intercept_context(self, length):
        self.__context = self.__context[:length]

harry_potter_book = Document('Harry Potter', 'J. K. Rowling', '... Forever Do not believe any thing is capable of thinking independently ...')

print(harry_potter_book.title)
print(harry_potter_book.author)
print(harry_potter_book.get_context_length())

harry_potter_book.intercept_context(10)

print(harry_potter_book.get_context_length())

print(harry_potter_book.__context)

########## 輸出 ##########

init function called
Harry Potter
J. K. Rowling
77
10

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-5-b4d048d75003> in <module>()
     22 print(harry_potter_book.get_context_length())
     23 
---> 24 print(harry_potter_book.__context)

AttributeError: 'Document' object has no attribute '__context'

三問對象

  1.如何在一個類中定義一些常量,每一個對象均可以方便訪問這些常量而不用從新構造?python

  答: 通常寫成大字,與函數並列聲明並賦值,注意是能夠修改的。ide

 

  2.若是一個函數不涉及到訪問修改這個類的屬性,而放到類外面有點不恰當,怎麼作才能更優雅呢?函數

  答: classmethod裝飾器聲明函數爲類函數,最經常使用的功能用於定義不一樣的init函數,如create_empty_book函數建立的對象 context必定爲'nothing',這比直接構造要清晰一些.this

       staticmethod裝飾器聲明函數爲靜態函數,能夠用來作一些簡單獨立的任務spa

class Document():
    
    WELCOME_STR = 'Welcome! The context for this book is {}.'
    
    def __init__(self, title, author, context):
        print('init function called')
        self.title = title
        self.author = author
        self.__context = context
    
    # 類函數
    @classmethod
    def create_empty_book(cls, title, author):
        return cls(title=title, author=author, context='nothing')
    
    # 成員函數
    def get_context_length(self):
        return len(self.__context)
    
    # 靜態函數
    @staticmethod
    def get_welcome(context):
        return Document.WELCOME_STR.format(context)


empty_book = Document.create_empty_book('What Every Man Thinks About Apart from Sex', 'Professor Sheridan Simove')


print(empty_book.get_context_length())
print(empty_book.get_welcome('indeed nothing'))

######### 輸出 ##########

init function called
7
Welcome! The context for this book is indeed nothing.

  3.既然類是一羣類似的對象的集合,那麼可不能夠是一羣類似的類的集合呢?code

  • 繼承類在生成對象時不會自動調用父類的構造函數,必須在init()函數中顯式調用父類中的構造函數 Entity.__init__(self, 'document')
  • 當子類對象調用 get_context_length 函數時,若是沒有實現此函數,會拋出get_context_length not implemented異常,這就使子類必須實現此函數。
  • 父類中的print_title 函數體現了繼承的優點,減小重複代碼.
class Entity():
    def __init__(self, object_type):
        print('parent class init called')
        self.object_type = object_type
    
    def get_context_length(self):
        raise Exception('get_context_length not implemented')
    
    def print_title(self):
        print(self.title)

class Document(Entity):
    def __init__(self, title, author, context):
        print('Document class init called')
        Entity.__init__(self, 'document')
        self.title = title
        self.author = author
        self.__context = context
    
    def get_context_length(self):
        return len(self.__context)
    
class Video(Entity):
    def __init__(self, title, author, video_length):
        print('Video class init called')
        Entity.__init__(self, 'video')
        self.title = title
        self.author = author
        self.__video_length = video_length
    
    def get_context_length(self):
        return self.__video_length

harry_potter_book = Document('Harry Potter(Book)', 'J. K. Rowling', '... Forever Do not believe any thing is capable of thinking independently ...')
harry_potter_movie = Video('Harry Potter(Movie)', 'J. K. Rowling', 120)

print(harry_potter_book.object_type)
print(harry_potter_movie.object_type)

harry_potter_book.print_title()
harry_potter_movie.print_title()

print(harry_potter_book.get_context_length())
print(harry_potter_movie.get_context_length())

########## 輸出 ##########

# Document class init called
# parent class init called
# Video class init called
# parent class init called
# document
# video
# Harry Potter(Book)
# Harry Potter(Movie)
# 77
# 120

抽像類的使用

  抽象類是爲父類而生的,不能對象化。若是有抽象函數也必須在子類中重寫才能使用。orm

from abc import ABCMeta, abstractmethod

class Entity(metaclass=ABCMeta):
    @abstractmethod
    def get_title(self):
        pass

    @abstractmethod
    def set_title(self, title):
        pass

class Document(Entity):
    def get_title(self):
        return self.title
    
    def set_title(self, title):
        self.title = title

document = Document()
document.set_title('Harry Potter')
print(document.get_title())

entity = Entity()

######### 輸出 ##########
Harry Potter

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-7-266b2aa47bad> in <module>()
     21 print(document.get_title())
     22 
---> 23 entity = Entity()
     24 entity.set_title('Test')

TypeError: Can't instantiate abstract class Entity with abstract methods get_title, set_title

 

參考:對象

  極客時間《Python核心技術與實戰》blog

相關文章
相關標籤/搜索