1. 程式人生 > >Python學習—面向對象學習下

Python學習—面向對象學習下

world 的區別 obj 更改 說明 函數 string 支持 是否

面向對象下

1.構造方法與析構方法

class People(object):
    # 構造方法:__init__(),在實例化對象時自動執行的方法
    def __init__(self, name, age):
        self.name = name
        self.age = age
        print("創建對象成功.......")
    #  析構函數:__del__(), 當你刪除對象時,自動調用的方法
    #  刪除對象:del 對象名
    def __del__(self):
        print("刪除對象成功.......")

1.構造函數:init()

用於初始化類的內容部狀態,也就是當該類被實例化的時候就會執行該函數。那麽我們就可以把要先初始化的屬性放到這個函數裏面。
init()方法是可選的,如果不提供,Python 會給出默認的init方法。一般數據的獲取需要定義的get和set方法

2.析構函數:del()

當使用del 刪除對象時,會調用他本身的析構函數,另外當對象在某個作用域中調用完畢,在跳出其作用域的同時析構函數也會被調用一次,這樣可以用來釋放內存空間。
del()也是可選的,如果不提供,則Python 會在後臺提供默認析構函數如果要顯式的調用析構函數,可以使用del關鍵字,方式:del 對象名

2.對象的str
repr方法

repr和str這兩個方法都是用於顯示的,str是面向用戶的,而repr面向程序員。
想使用print(Object)顯示對象,那就需要重構str。想直接輸入類對象Object來打印,那就需要重構repr,當然它也可以使用print(Object)顯示對象。區別在於:當你打印一個類的時候,那麽print首先調用的就是類裏面的定義的str方法,而不是repr方法,在沒有str方法時才會去調用repr方法。

#定義類
>>> class Test():
    def __init__(self):
        self.ppx = "hello,python."
#實例化類,然後想直接獲取類的一些信息
>>> t = Test()
>>> t
<__main__.Test object at 0x0000000002F3EF28>
>>> print(t)
<__main__.Test object at 0x0000000002F3EF28>

在沒有str或者repr方法時,上面打印類對象顯示的是對象的內存地址
下面我們重構下該類的repr以及str,看看它們倆的區別

>>> class TestRepr(Test):
    def __repr__(self):
        return "Show:%s"%self.ppx
>>> t1 = TestRepr()
>>> t1
Show:hello,python.
>>> print(t1)
Show:hello,python.

可以看到,重構repr方法後,不管直接輸出對象還是通過print打印的信息都按我們repr方法中定義的格式進行顯示

>>> class TestStr(Test):
    def __str__(self):
        return "Show:  %s"%self.ppx
>>> t2 = TestStr()
>>> t2
<__main__.TestStr object at 0x00000000031C33C8>
>>> print(t2)
Show:  hello,python.

直接輸出對象ts時並沒有按我們str方法中定義的格式進行輸出,而用print(Object)輸出的信息才會這樣顯示。

3.formate方法

1.通過位置來填充字符串

print("hello %s" % (‘world‘))

print("hello {0}".format((1, 2, 3, 4)))
print("hello {0} {1} {0} {1}".format((1, 2, 3, 4), "python"))
print("hello {0:.3f}".format(1.8989))

運行輸出:
hello world
hello (1, 2, 3, 4)
hello (1, 2, 3, 4) python (1, 2, 3, 4) python

2.通過key來填充

print("max:{max} min:{min}".format(min=10, max=100))

運行輸出:
max:100 min:10

3.通過下標/index填充

point = (3,4)
print("x:{0[0]}, y:{0[1]}".format(point))

輸出:
x:3, y:4

4.通過字典的key

d = {‘max‘:100.7849758475976, ‘min‘:10.4756895769857985}
print("max:{max:.2f} min:{min:.3f}".format(**d))

運行輸出:
max:100.78 min:10.476

5. oop對象進行操作

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

    # 打印對象時自動調用;str(對象)
    def __str__(self):
        return "書名:{0.name} 狀態:{0.state}".format(self)
        # return "書名:{d.name} 狀態:{d.state}".format(d=self)

b = Book("java", ‘aa‘, 1, ‘Index‘)
print(b)

運行輸出:
書名:java 狀態:1

6. 對象中的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):
        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‘))     #傳入參數

運行輸出:
2019-8-25
8/25/2019

4.關於@property

習慣了高級語言的嚴謹,總想對屬性加以訪問控制,相對安全些,比如直接在init中定義公用屬性,從封裝性來說,它是不好的寫法。屬性訪問控制機制,其一是@propery關鍵字。用此關鍵字,其獲取、設置函數,須與屬性名一致。
br/>屬性訪問控制機制,其一是@propery關鍵字。用此關鍵字,其獲取、設置函數,須與屬性名一致。

from requests.compat import basestring

class Animal(object):
    def __init__(self, name, age):
        self._name = name
        self._age = age
        self._color = ‘Black‘

    # 將普通方法變為屬性方法
    @property
    def name(self):
        return self._name

    # 當更改name的值時,自動調用下面這個方法。這樣就可以更改屬性的值了
    @name.setter
    def name(self, value):
        if isinstance(value, basestring):
            self._name = value
        else:
            self._name = ‘No name‘

    #獲取值
    @name.getter
    def get(self):
        return self.name

    @property
    def age(self):
        return self._age

    @age.setter
    def age(self, value):
        if value > 0 and value < 100:
            self._age = value
        else:
            self._age = 0

    @property
    def color(self):
        return self._color

    @color.setter
    def color(self, value):
        self._color = value;

a = Animal(‘black dog‘, 3)
a.name = ‘white dog‘
a.age = 55
a.color = ‘red‘
print(‘Name:‘, a.name)
print(‘Age:‘, a.age)
print(‘Color:‘, a.color)
print(a.get)

運行結果:
Name: white dog
Age: 55
Color: red
white dog

5.類裏面的切片與索引

魔術方法getitemsetitemdelitem
1.對列表的操作

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])

# *********************************索引**************************
print(s[0])
print(s[1])
print(s[2])

#更改值
s[0] = 200
print(s[0])

print(s.scores)
#刪除值
del s[0]
print(s.scores)

# *********************************切片**************************
print(s[1:3])
s[1:3] = [0,0]
print(s[:])
del s[:-1]
print(s[:])
print(s[0])

運行結果:
101
100
100
200
[200, 100, 100]
[100, 100]
[100]
[100, 0, 0]
[0]
0

2.對字典的操作

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值***********************
print(s.__dict__)
print(s[‘name‘])
print(s[‘scores‘])

s[‘name‘] = ‘westo1‘
print(s[‘name‘])
del s[‘name‘]   #刪除一個鍵值對
# print(s[‘name‘])  #如果查值,會報錯:key不存在

運行結果:
{‘name‘: ‘westos‘, ‘scores‘: [101, 100, 100]}
westos
[101, 100, 100]
westo1

6.call()方法

當一個類實現call方法時,這個類的實例就會變成可調用對象。即函數。
1.

class ClassA:

    def __call__(self, *args, **kwargs):
        print(‘call ClassA instance.......‘)

# ClassA實現了__call__方法
a = ClassA()
#這個時候,ClassA的實例a,就變成可調用對象
#調用a(),輸出call ClassA instance,說明是調用了__call__函數

a()
# 其實a()等同於a.__call__(),它本質上就是後者的縮寫
a.__call__()

運行結果:
call ClassA instance.......
call ClassA instance.......

2.

class Dddd(object):
  def __init__(self, origin):
    self.origin = origin
    print("origin :"+str(origin))
  def __call__(self, x):
    print("x :"+str(x))

p = Dddd(100)
p(2000)

運行結果:
origin :100
x :2000

7.實現一個單例模式

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

    # 實例化對象之前先執行下面這個new魔術方法
    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)

運行結果:
<__main__.Student object at 0x7fedfa2ebef0>
<__main__.Student object at 0x7fedfa2ebef0>

可以看見,對象s1,s2他們指向的地址相同,即他們時同一個對象。而不是兩個相同值的對象。

8.類中的安全上下文with語句

enter()與exit()

class MyOpen(object):
    def __init__(self, filename, mode=‘r‘):
        self._name = filename
        self._mode = mode

    # 當with語句開始運行的時候,執行此方法;
    def __enter__(self):
        self.f = open(self._name, self._mode)
        return  self.f

    # 當with語句執行結束之後運行;
    def __exit__(self, exc_type, exc_val, exc_tb):
        self.f.close()

with MyOpen(‘/etc/passwd‘) as f:
    print(f.closed)
    print(f.read(5))

print(f.closed)

運行如果:
False
root:
True

9.反射

反射:主要是指程序可以訪問、檢測和修改它本身狀態或行為的一種能力(自省)。
python面向對象中的反射:通過字符串的形式操作對象相關的屬性。python中的一切事物都是對象(都可以使用反射)。即 讓對象告訴我們相關信息(對象擁有的屬性和方法, 對象所屬的類等....)

四個可以實現自省的函數

hasattr(object,name)
判斷object中有沒有一個name字符串對應的方法或屬性,註意私有屬性或者方法不能判斷出來
getattr(object, name, default=None)
獲取object中有沒有對應的方法和屬性,私有屬性或者方法不能判斷出來不能獲取到。default是設置當獲取不到時的返回值,默認為None
setattr(x, y, v)
修改或添加對象的屬性
delattr(x, y)
刪除類或對象的屬性

class Student(object):
    """
    這是student類的幫助文檔

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

    def get_score(self):
        return  "score"

    def get_grade(self):
        return ‘grade‘

s1 = Student("fentiao", 10)
print(type(s1))
print(isinstance(s1, Student))
print(isinstance(‘hello‘, Student))

#  跟據對象可以獲取的內容
print(s1.__class__) #類信息
print(s1.__dict__)  #生成字典
print(s1.__doc__)   #獲取幫助文檔

#  hasattr, getattr, setattr, delattr
# hasattr: 判斷對象是否包含對應的屬性或者方法名;
print(hasattr(s1, ‘name‘))
print(hasattr(s1, ‘__age‘))  # 私有屬性, 私有方法, 是不能判斷的;
print(hasattr(s1, ‘score‘))

print(hasattr(s1, ‘get_score‘))
print(hasattr(s1, ‘set_score‘))

# getattr
print(getattr(s1, ‘name‘))
print(getattr(s1, ‘__age‘, ‘no attr‘))
print(getattr(s1, ‘get_score‘, ‘no method‘))  # 獲取方法名, 如果要執行方法, 直接調用即可
print(getattr(s1, ‘set_score‘, ‘no method‘))  # 獲取方法名, 如果要執行方法, 直接調用即可

# setattr:
# 修改某個屬性的值
setattr(s1, ‘name‘, ‘westos‘)
print(getattr(s1, ‘name‘))

# 添加某個屬性及對應的值;
setattr(s1, ‘score‘, 100)
print(getattr(s1, ‘score‘))

# 修改方法
def get_score1():
    return "這是修改的方法內容"
setattr(s1, ‘get_score‘, get_score1)
print(getattr(s1, ‘get_score‘)())

def set_score():
    return  "這是添加的方法"
# 添加方法
setattr(s1, ‘set_score‘, set_score)
print(getattr(s1, ‘set_score‘)())

# delattr
delattr(s1, ‘name‘)
print(hasattr(s1, ‘name‘))

print(hasattr(s1, ‘set_score‘))
delattr(s1, ‘set_score‘)
print(hasattr(s1, ‘set_score‘))

運行結果:
<class ‘__main__.Student‘>
True
False
<class ‘__main__.Student‘>
{‘name‘: ‘fentiao‘, ‘_Student__age‘: 10}

    這是student類的幫助文檔

True
False
False
True
False
fentiao
no attr
<bound method Student.get_score of <__main__.Student object at 0x7efc6b8a3ac8>>
no method
westos
100
這是修改的方法內容
這是添加的方法
False
True
False

Python學習—面向對象學習下