對象的組合、魔術、反射、異常


今日內容概要

  • 組合
  • 面向對象的內置函數(魔術方法、魔法)
  • 反射
  • 異常

內容詳細

image

組合

# 什么是組合
	就是一個對象擁有一個屬性
    但是該屬性的值 是另外一個對象
    
# 繼承
	其實就可以描述為:
        滿足什么是什么的關系 is-a的關系
'''
is-a 從字面上看就表示"是一個"的意思 根據繼承的特性
	一個派生類對象(子類) 可以看成是一個基類(父類)對象 
	也就是說一個派生類對象"是一個"基類對象,所以這種名稱符合對這種特性的概括。
'''

# 繼承是一把雙刃劍 並不是繼承的越多越好 多繼承盡量少一些

# 例1
class Foo:
    def __init__(self, m):
        self.m = m

class Bar():
    def __init__(self, n):
        self.n = n

obj = Foo(10)  # m = 10
obj1 = Bar(20)  # n = 20

obj.x = obj1  # obj.x就是一個組合 就是一個對象擁有一個屬性obj.x 但是該屬性的值 是另外一個對象obj1

print(obj.__dict__)  # {'m': 10, 'x': <__main__.Bar object at 0x000001F73E14B470>}
# obj  就是一個超級對象 不僅可以拿自己對象中的屬性 還可以拿到其他對象中的屬性
print(obj.x.n)  # 20  obj.x就相當於obj1
print(obj1.n)  # 20



# 例2
# 父類
class People():
    school = 'SH'

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


class Admin(People):
   pass

# 父類
class Course():
    def __init__(self, name, period, price, ):
        self.name = name
        self.period = period
        self.price = price


python = Course('python', '6mon', 10000)  # 實例化對象 課程就出來了
linux = Course('linux', '5mon', 20000)  # 實例化對象 課程就出來了

# 子類
class Student(People, Course):
    def __init__(self, name, age, gender, course=None):
        if course is None:
            course = []
        self.courses = course
        super().__init__(name, age, gender, )

    def choose_course(self, stu_obj, course):
        stu_obj.courses.append(course)


stu = Student('ly', 19, 'male', 'python')
print(stu.name)  # ly


stu = Student('ly', 20, 'male')
# 課程已經有過了
# python = Course('python', '6mon', 10000)  # 實例化對象 課程就出來了
# linux = Course('linux', '5mon', 20000)  # 實例化對象 課程就出來了
stu.courses.append(python)
stu.courses.append(linux)
print(stu.courses)  # 內存地址 [<__main__.Course object at 0x00000186D04BB390>, <__main__.Course object at 0x00000186D04BB3C8>]
# 實例化后結果 [python, linux] 列表里面是兩個內存地址
for course in stu.courses:  # 通過內存地址空間中找屬性
    print(course.price)
# 10000
# 20000

# 子類
class Teacher(People, Course):
    def __init__(self, name, age, gender, level):
        self.level = level
        super().__init__(name, age, gender, )

    def score(self, stu_obj, score):
        stu_obj.score = score


tea = Teacher('ly', 19, 'male', 10)
tea.course = linux
print(tea.course.name)  # 課程名 linux
print(tea.course.price)  # 課程價格 20000
print(tea.course.period)  # 課程周期 5mon

image

面向對象的內置函數

# 1. __init__()
    調用類的時候自動觸發的方法
# 2. __str__()
    只要打印對象的時候 就會自動觸發的方法
# 3. __del__()
# 4. __enter__()
# 5. __exit__()
# 6. __call__()


# 1. __init__() 2. __str__()
class Student():
    school = 'SH'

    # 調用類的時候觸發
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def tell(self):
        print('name: %s, age: %s' % (self.name, self.age))

    # 只要打印對象的時候,就會自動觸發的函數
    # 但是返回值只能是字符串
    def __str__(self):
        return 'name:%s' % self.name
        # return 123  報錯 返回值只能是字符串

stu = Student('ly', 20)
print(stu)  # name:ly 就相當於打印 print(stu.__str__())

f = open('a.txt', mode='w')
print(f)  # 結果是經過底層處理的數據  <_io.TextIOWrapper name='a.txt' mode='w' encoding='cp936'>

# 3. __del__()
class Student():
    school = 'SH'

    # 調用類的時候觸發
    def __init__(self, name, age):
        self.name = name
        self.age = age
        self.f = open('a.txt', 'r')

    # 1. 手動執行del
    # 2. 程序執行完畢觸發
    def __del__(self):
        print('from __del__')
        self.f.close()

stu = Student('ly', 19)
del stu.school  # 報錯 因為stu對象默認是空

del Student.school  # from __del__  后走
print('end=>>>>>>>>>>>>')  # 先走

del stu.name  # from __del__
print(stu.school)
print('end=>>>>>>>>>>>>')


# 4. __enter__() 5. __exit__()
class Open:
    def __init__(self,name):
        self.name=name

    def __enter__(self):
        print('出現with語句,對象的__enter__被觸發,有返回值則賦值給as聲明的變量')  # 1
        return self
        # return 123
        # __enter__執行之后 繼續執行with代碼體


    def __exit__(self, exc_type, exc_val, exc_tb):  # with代碼體 執行完之后 執行__exit__
        print('with中代碼塊執行完畢時執行我啊')  # 4

with Open('a.txt') as f:
    print('=====>執行代碼塊')  # 2
    print(f)  # <__main__.Open object at 0x00000246D7B793C8>  # 3
    
print(f, f.name)  # 5


# 6. __call__()
class Foo:

    def __init__(self):
        pass

    # 對象加括號自動觸發
    def __call__(self, *args, **kwargs):
        print('__call__')

obj = Foo()  # 執行 __init__

# 一切皆對象 對象就可以加括號
obj()  # __call__


'''
a = list([1, 2, 3])
# a.append(4)  # 就相當於 list.append(a, 4)
list.append(a, 5)
print(a)  # [1, 2, 3, 5]
'''

image

反射

# 反射是指:對象通過字符串來操作屬性

class Student():
    school = 'sh'
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def func(self):
        print('from func')

stu = Student('ly', 18)

print(stu.name)  # ly
print(stu."name")  # 報錯 不能直接用字符串
print(stu.__dict__['name'])  # ly 存在則正常獲取屬性
print(stu.__dict__['name11'])  # 不存在的情況直接報錯 


# 1. getattr
print(getattr(stu, 'name1', None))  # None 相當於 stu.name 第一個參數傳對象 第二個傳屬性 第三個傳找不到的返回結果
stu.func()  # from func 直接調用
print(getattr(stu, 'func'))  # 通過字符串調用 <bound method Student.func of <__main__.Student object at 0x0000020BB6FBBD30>>
getattr(stu, 'func')()  # from func 必須掌握

# 2. setattr
setattr(stu, 'x', 123)  # 第一個傳對象 第二個傳屬性名 第三個傳屬性值
print(stu.__dict__)  # {'name': 'ly', 'age': 18, 'x': 123}

# 3. hasattr
print(hasattr(stu, 'name'))  # True 確認對象中是否有屬性 第一個傳對象 第二個傳屬性
print(hasattr(stu, 'name1'))  # False

# 4. delattr
delattr(stu, 'name')  # 刪除 第一個傳對象 第二個傳屬性
print(stu.__dict__)  # {'age': 18}

# 類也可以使用
print(getattr(Student, 'school'))

# 模塊也可以使用
import time

time.sleep(1)
getattr(time, 'sleep')(2)

# 導模塊底層寫法 __import__('time') 就相當於 import time

time = __import__('time')  # 就相當於 import time 導入模塊
time.sleep(3)  # 用法一樣

image

異常

1.什么是異常
	異常就是錯誤發生的信號
    '''如果不對該信號做處理 那么異常之后的代碼不會執行'''
  
# 異常種類
	語法錯誤
    	不被允許的 print(12
    邏輯錯誤
    	被允許 但盡量不要出現
    	a = [1, 2, 3]
        print(a[5])

2.為什么要用異常
	增強代碼的健壯性

3.怎么用異常
	
try:
    被監測代碼
except 異常的類型:
    pass  # 異常處理流程
except 異常的類型:
    pass  # 異常處理流程
except 異常的類型:
    pass  # 異常處理流程
except Exception as e:  # 萬能異常 不管什么類型錯誤 都可以接收
    pass
else:
    # 當被監測代碼沒有發生異常的時候,觸發的
    pass
finally:
    不管被監測的代碼有沒有出錯,都執行 
    pass
         

image


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM