1. 程式人生 > >python---面向物件2

python---面向物件2

1構造方法與析構方法

from collections import Counter


class People(object):
    # 例項化物件時自動執行
    def __init__(self, name, age):
        # 把屬性和物件名繫結在一起, 便於訪問物件的屬性.
        self.name = name
        self.age = age
        print("建立物件成功.......")
    #  解構函式, 當你刪除物件時, 自動呼叫的方法。
    #   del 物件名或者程式執行結束之後
    def
__del__(self):
print("刪除物件成功.......") if __name__ == '__main__': # 建立物件 p1 = People('fentiao', 12) # # del p1

這裡寫圖片描述

2.物件str與repr方法

from collections import Counter


class People(object):
    # 例項化物件時自動執行
    def __init__(self, name, age):
        # 把屬性和物件名繫結在一起, 便於訪問物件的屬性.
self.name = name self.age = age print("建立物件成功.......") # 解構函式, 當你刪除物件時, 自動呼叫的方法。 # del 物件名或者程式執行結束之後 def __del__(self): print("刪除物件成功.......") # __str__和__repr__都是對物件的字串顯示, 使用場景不同. # 如果沒有__str__的時候, 自動呼叫__repr__方法的內容. def __str__(self): # print(物件名) print(str(物件名))
# print('People(%s, %d)' %(self.name, self.age)) return 'People(%s, %d)' %(self.name, self.age) def __repr__(self): # print(repr(物件名)) 或者互動式環境中直接: 物件名 return "People(%s)" %(self.name) def __hello(self): print("hello") def world(self): self.__hello() if __name__ == '__main__': # 建立物件 p1 = People('fentiao', 12) print(p1) print(p1.__str__()) p1.world() # print(str(p1)) # print(repr(p1))

這裡寫圖片描述

3.圖書管理系統

# 假設每本書只有一本

class Book(object):
    def __init__(self, name, author, state, bookIndex):
        self.name = name
        self.author = author
        # 0:'已借出' 1:'未借出'
        self.state = state
        self.bookIndex = bookIndex


    def __str__(self):
        return  'Book(%s, %d)' %(self.name, self.state)

class   BookManage(object):
    # 存放所有書籍資訊, 列表裡面存放的是Book物件
    books = []

    def start(self):
        """圖書管理系統初始化資料"""
        self.books.append(Book('python', 'Guido', 1, 'IN23445'))
        self.books.append(Book('java', 'Guido1', 1, 'IN23445'))
        self.books.append(Book('C++', 'Guido2', 1, 'IN23445'))
        print("初始化資料成功!")

    def Menu(self):
        """圖書管理選單欄"""
        while True:
            print("""
                        圖書管理操作

            1). 新增書籍
            2). 刪除資料
            3). 查詢書籍

            4). 退出
            """)
            choice = input("請輸入你的選擇:")
            if choice == '1':
                self.addBook()
            elif choice == '2':
                self.delBook()
            elif choice == '3':
                self.isBookExist('python')
            elif choice == '4':
                exit()
            else:
                print("請輸入正確的選擇!")

    def addBook(self):
        print("新增書籍".center(0, '*'))
        name = input("書籍名稱:")
        bObj = self.isBookExist(name)
        if bObj:
            print("書籍%s已經存在" %(bObj.name))
        else:
            self.books.append(Book(name,input("作者:"), 1, input("存放位置:")))
            print("書籍%s新增成功" %(name))

    def delBook(self):
        pass


    def borrowBook(self):
        pass

    def returnBook(self):
        pass

    def isBookExist(self, name):
        """檢測書籍是否存在"""
        # 1. 依次遍歷列表books裡面的每個元素
        # 2. 如果有一個物件的書名和name相等, 那麼存在;
        # 3. 如果遍歷所有內容, 都沒有發現書名與name相同, 書籍不存在;
        for book in self.books:
            if book.name == name:
                # 因為後面需要
                return book
        else:
            return  False

if __name__ == "__main__":
    bManger = BookManage()
    bManger.start()
    bManger.Menu()

4.字串的format方法


print("name:%s, age:%d, scores:%s" % ('westos', 10, dict(a=1, b=2)))
print("name:%s, age:%d, scores:%s" % ('westos', 10, (1, 2)))
print("name:%s, age:%d, name:%s" % ('westos', 10, 'westos'))

# 通過位置填充字串
print("name:{0}, age:{1}, scores:{2}".format('westos', 10, [100, 100, 100]))
print("name:{0}, age:{1}, scores:{0}".format('westos', 10))
print("name:{0}, id:{1:.3f}, scores:{0}".format('westos', 19.2332435))

# 通過key值填充字串
d = {'max': 100, 'min': 10}
print("MAX: {max}, MIN:{min}".format(max=100, min=10))
print("MAX: {max}, MIN:{min}".format(**d))

# 通過下標或者索引值填充
point = (3,4)
print("x:{0[0]}, y:{0[1]}".format(point))


# 面向物件操作
class Book(object):
    def __init__(self, name, author, state, bookIndex):
        self.name = name
        self.author = author
        # 0:'已借出' 1:'未借出'
        self.state = state
        self.bookIndex = bookIndex

    def __str__(self):
        return  'Book(%s, %d)' %(self.name, self.state)
b = Book('python', 'guido', 1, 'IND444')
print("name:{b.name}, state:{b.state}, author:{b.state}".format(b=b))
print("name:{0.name}, state:{0.state}, author:{0.state}".format(b))

5.format魔術方法


formats = {
    'ymd':"{d.year}-{d.month}-{d.day}",
    'mdy':"{d.month}/{d.day}/{d.year}",
}


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

    # format方法: format(物件名)時自動呼叫
    def __format__(self, format_spec=None):
        # return "這是顯示format的內容"
        # if format_spec:
        #     format_spec = format_spec
        # else:
        #     format_spec = 'ymd'
        if not format_spec:
            format_spec = 'ymd'
        fmt = formats[format_spec] # "{d.year}-{d.month}-{d.day}".format(d=d)
        return  fmt.format(d=self)

d = Date(2019, 8, 25)
print(format(d))
print(format(d, 'mdy'))


# print(d.__format__('ymd'))
# print(format(d, 'ymd'))


# ‘ymd’ ===> ‘2019-8-25’
# ‘mdy’ ===> '8/25/2019'

format簡化版


class Date(object):
    def __init__(self, year, month, day):
        self.year = year
        self.month = month
        self.day = day
    # format方法: format(物件名)時自動呼叫
    def __format__(self, format_spec=None):
        if not format_spec:
            return  "%s-%s-%s" %(self.year, self.month, self.day)
        else:
            if format_spec == 'ymd':
                return  "%s-%s-%s" %(self.year, self.month, self.day)
            elif format_spec == 'dmy':
                return   "%s/%s/%s" %(self.day, self.month, self.year)
            else:
                return  "error format"
d = Date(2019, 8, 25)
print(format(d))
print(format(d, 'ymd'))
print(format(d, 'dmy'))


# print(d.__format__('ymd'))
# print(format(d, 'ymd'))


# ‘ymd’ ===> ‘2019-8-25’
# ‘mdy’ ===> '8/25/2019'

這裡寫圖片描述

6.類內部裝飾器property

class Book(object):
    def __init__(self, name, author, state, bookIndex):
        self.name = name
        self.author = author
        # 0:'已借出' 1:'未借出'
        self.__state = state
        self.bookIndex = bookIndex

    # 將類方法變成類屬性
    # 使用時, 沒有裝飾器b.state()
    # 使用時, 有裝飾器b.state
    @property
    def state(self):
        if self.__state == 0:
            return  '已借出'
        elif self.__state == 1:
            return  '未借出'
        else:
            return  "狀態異常"
    # 當修改屬性state時, 自動執行下面的方法; b.state = 10
    @state.setter
    def state(self, value):
        # if value == 0 or value == 1:
        if value in (0,1):
            # 更新書籍的狀態
            self.__state = value

    @state.deleter
    def state(self):
        print("is deleteing......")

    def __str__(self):
        return  'Book(%s, %d)' %(self.name, self.__state)


b = Book('python', 'guido', 1, 'chddf')
# print(b.state)
#
# # 1). 書籍的狀態可以人以改變, 並不能限制只能為0或者1;
#   2). 書籍狀態如何友好的顯示?
# b.state = 10
# print(b.state)

# 3). 問題解決, 但是呼叫比較複雜, 可讀性不高.
# print(b.get_state())
# print(b.set_state(10))
# print(b.get_state())


# 4).
print(b.state)
b.state = 0
print(b.state)

del  b.state

7.實現類的切片與索引

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

    # 支援索引; s[index]
    def __getitem__(self, index):
        # print("獲取索引對應的value值")
        return  self.scores[index]


    # s[索引] = 修改的值
    def __setitem__(self, index, value):
        self.scores[index] = value

    # del s[索引]
    def __delitem__(self, index):
        del self.scores[index]


    def hello(self):
        return  "hello"
s = Student('westos', [101, 100, 100])




# *********************************index**************************
# print(s[0])
# print(s[1])
# print(s[2])

# # 0, 200
# s[0] = 200
# print(s[0])


# print(s.scores)
# del s[0]
# print(s.scores)


#**************************key獲取value值***********************
# 可以獲取所有的屬性為key值, 以及對應的value值, 並封裝為一個字典返回.
print(s.__dict__)
# str, list
# li = [1,2,3,4,5,6]
# __getitem__:  li[0]   === __getslice__
# __setitem__: li[0] = 10  == __setslice__
# __delitem__: del li[0]   == __delslice__


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

    # 支援索引; s[key]
    def __getitem__(self, key):
        # print("獲取索引對應的value值")
        return  self.__dict__[key]


    # s[key] = 修改的值
    def __setitem__(self, key, value):
        self.__dict__[key] = value

    # del s[key]
    def __delitem__(self, key):
        del self.__dict__[key]


    def hello(self):
        return  "hello"
s = Student('westos', [101, 100, 100])

#**************************key獲取value值***********************
# 可以獲取所有的屬性為key值, 以及對應的value值, 並封裝為一個字典返回.
# print(s.__dict__)
print(s['name'])
print(s['scores'])


s['name'] = 'westo1'
print(s['name'])

del s['name']
print(s['name'])
# str, list
# li = [1,2,3,4,5,6]
# __getitem__:  li[0]   === __getslice__
# __setitem__: li[0] = 10  == __setslice__
# __delitem__: del li[0]   == __delslice__


class Student(object):
    def __init__(self, name, scores):
        self.name = name
        self.scores = scores
    def __getitem__(self, key):
        return self.scores[key]
    def __setitem__(self, key, value):
        self.scores[key] = value
    def __delitem__(self, key):
        del self.scores[key]




# 對於切片的操作*******
s = Student('westos', [101, 90, 101])
print(s[1:3])
s[1:3] = [0,0]
print(s[:])
del s[:-1]
print(s[:])
print(s[0])

8.重複與連線與成員操作符的實現

from collections import Iterable


class Student(object):
    def __init__(self, name, scores):
        self.name = name
        self.scores = scores
        self.power = 100
    # obj1 + obj2
    def __add__(self, other):
        # 更新self物件的power屬性值;
        self.power =  self.power + other.power
        return  self
    # obj1 * 3
    def __mul__(self, other):
        # *的效果是, 能量*power
        return  self.power * other
    # 成員操作符; item in obj1
    def __contains__(self, item):
        return  item in self.scores
    # 可以for迴圈迭代
    def __iter__(self):
        """
        iter([1,2,3,4,5])
        <list_iterator object at 0x7f6e1f51ffd0>
        iter({1,2,3,4,5})
        <set_iterator object at 0x7f6e1f567318>

        """
        # 迭代返回的是成績
        return  iter(self.scores)
    def __repr__(self):
        return  "Student:%s,%s" %(self.name, self.power)
# print("hello " + "world")
# print([1,2,3] + [3,4,5])

s1 = Student('westos1', [101,100,100])
s2 = Student('westos2', [100,100,100])
s3 = Student('westos3', [100,100,100])

# 連線的實現;
# "hello" + "world" + "hwllo"
print(s1 + s2 + s3)
# # a = 1 ; a+=1 a=2
# # str = "h"; str+='e' str=''he
# s1 += s2
# print(s1)


# 重複:
# a = 3; print(a*3)
# s = 'a'; print(s*3)
# li = [1,2,3]; print(li*3)
# print(s1*3)


# 成員操作符
# print(s1.scores)
# print(200 in s1)
# print(100 in s1)
# print(200 not in s1)
# print(100 not in s1)

# for迴圈迭代
# for i in s1:
#     print(i)
# print(isinstance(s1, Iterable))

9.比較大小—計算長度

from django.core.paginator import Page


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

    def __add__(self, other):
        # 更新self物件的power屬性值;
        self.power =  self.power + other.power
        return  self
    # obj1 > obj2
    def __gt__(self, other):
        return  self.power > other.power
    # obj >= obj2
    __ge__ = lambda  self, other: self.power >= other.power
    # obj1 ==  obj2
    def __eq__(self, other):
        return self.power ==  other.power
    def __ne__(self, other):
        return  self.power !=  other.power
        # return  not self.__eq__(other)
    def __repr__(self):
        return  "Student:%s,%s" %(self.name, self.power)
    def __len__(self):
        return  len(self.scores)


s1 = Student('westos1', [101,100,100], 100)
s2 = Student('westos2', [100,100,100], 101)
s3 = Student('westos3', [100,100,100], 80)



# print(s1+s2)
# print(s1 > s2 > s3)
# print(s1>=s2)
# print(s1<s2)
# print(s1 == s2)
# print(s1 != s2)


print(len(s1))

10.call方法

# 實現一個單例模式====
from django.core.paginator import Page


class Student(object):
    def __init__(self, name, scores, power):
        self.name = name
        self.scores = scores
        self.power = power
    def __call__(self, *args, **kwargs):
        return "物件被呼叫......"
    # class: 例項化物件之前執行
    def __new__(cls, *args, **kwargs):
        # 判斷是否obj物件是否已經被建立, 如果沒有被建立, 則建立,
        if not hasattr(cls, 'obj'):
            cls.obj = object.__new__(cls)
        # 如果已經建立成功,則返回建立好的物件
        return  cls.obj
s1 = Student('westos1', [101,100,100], 100)
s2 = Student('westos1', [101,100,100], 100)
print(s1)
print(s2)

11.參考程式碼

class Paginator(object):

    def __init__(self, object_list, per_page, orphans=0,
                 allow_empty_first_page=True):
        self.object_list = object_list
        self._check_object_list_is_ordered()
        self.per_page = int(per_page)
        self.orphans = int(orphans)
        self.allow_empty_first_page = allow_empty_first_page

    def validate_number(self, number):
        """
        Validates the given 1-based page number.
        """
        try:
            number = int(number)
        except (TypeError, ValueError):
            raise PageNotAnInteger(_('That page number is not an integer'))
        if number < 1:
            raise EmptyPage(_('That page number is less than 1'))
        if number > self.num_pages:
            if number == 1 and self.allow_empty_first_page:
                pass
            else:
                raise EmptyPage(_('That page contains no results'))
        return number

    def page(self, number):
        """
        Returns a Page object for the given 1-based page number.
        """
        number = self.validate_number(number)
        bottom = (number - 1) * self.per_page
        top = bottom + self.per_page
        if top + self.orphans >= self.count:
            top = self.count
        return self._get_page(self.object_list[bottom:top], number, self)

    def _get_page(self, *args, **kwargs):
        """
        Returns an instance of a single page.

        This hook can be used by subclasses to use an alternative to the
        standard :cls:`Page` object.
        """
        return Page(*args, **kwargs)

    @cached_property
    def count(self):
        """
        Returns the total number of objects, across all pages.
        """
        try:
            return self.object_list.count()
        except (AttributeError, TypeError):
            # AttributeError if object_list has no count() method.
            # TypeError if object_list.count() requires arguments
            # (i.e. is of type list).
            return len(self.object_list)

    @cached_property
    def num_pages(self):
        """
        Returns the total number of pages.
        """
        if self.count == 0 and not self.allow_empty_first_page:
            return 0
        hits = max(1, self.count - self.orphans)
        return int(ceil(hits / float(self.per_page)))

    @property
    def page_range(self):
        """
        Returns a 1-based range of pages for iterating through within
        a template for loop.
        """
        return six.moves.range(1, self.num_pages + 1)

    def _check_object_list_is_ordered(self):
        """
        Warn if self.object_list is unordered (typically a QuerySet).
        """
        if hasattr(self.object_list, 'ordered') and not self.object_list.ordered:
            warnings.warn(
                'Pagination may yield inconsistent results with an unordered '
                'object_list: {!r}'.format(self.object_list),
                UnorderedObjectListWarning
            )


QuerySetPaginator = Paginator   # For backwards-compatibility.


class Page(collections.Sequence):

    def __init__(self, object_list, number, paginator):
        self.object_list = object_list
        self.number = number
        self.paginator = paginator

    def __repr__(self):
        return '<Page %s of %s>' % (self.number, self.paginator.num_pages)

    def __len__(self):
        return len(self.object_list)

    def __getitem__(self, index):
        if not isinstance(index, (slice,) + six.integer_types):
            raise TypeError
        # The object_list is converted to a list so that if it was a QuerySet
        # it won't be a database hit per __getitem__.
        if not isinstance(self.object_list, list):
            self.object_list = list(self.object_list)
        return self.object_list[index]

    def has_next(self):
        return self.number < self.paginator.num_pages

    def has_previous(self):
        return self.number > 1

    def has_other_pages(self):
        return self.has_previous() or self.has_next()

    def next_page_number(self):
        return self.paginator.validate_number(self.number + 1)

    def previous_page_number(self):
        return self.paginator.validate_number(self.number - 1)

    def start_index(self):
        """
        Returns the 1-based index of the first object on this page,
        relative to total objects in the paginator.
        """
        # Special case, return zero if no items.
        if self.paginator.count == 0:
            return 0
        return (self.paginator.per_page * (self.number - 1)) + 1

    def end_index(self):
        """
        Returns the 1-based index of the last object on this page,
        relative to total objects found (hits).
        """
        # Special case for the last page because there can be orphans.
        if self.number == self.paginator.num_pages:
            return self.paginator.count
        return self.number * self.paginator.per_page