1. 程式人生 > 其它 >當你上機課摸魚時猛地發現已經半個多月沒更部落格之後。。。

當你上機課摸魚時猛地發現已經半個多月沒更部落格之後。。。

組合

組合和繼承一樣也是用來解決類與類之間的冗餘問題

一、組合就是物件擁有一個屬性,該屬性的值就是另外一個物件

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


class Student(People):

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


class Teacher(People):
	def __init__(self, name, age, gender, level):
		super().__init__(name, age, gender)
		self.level = level
		print('%s|%s|%s|%s' % (self.name, self.age, self.gender, level))


class Course:
	def __init__(self, course_name, course_price, course_period):
		self.course_name = course_name
		self.course_price = course_price
		self.course_period = course_period

	def tell(self):
		print('課程價格:%s|課程名稱:%s|課程週期:%s' % (self.course_price, self.course_name, self.course_period))


stu1 = Student('judy', 19, 'female')
python = Course('python', 19800, '6mons')
linux = Course('linux', 19000, '5mons')

stu1.course = []  # stu1相當於一個字典,給stu1這個物件加一個建值對
stu1.course.append(python)  # stu1這個屬性是course這個類的物件
stu1.course.append(linux)
for i in stu1.course:  # 遍歷得到物件,然後可以呼叫
	i.tell()

面向物件的內建函式

一、列印物件時觸發函式

		#  __str__
class Student:
	def __init__(self, name, age):
		self.name = name
		self.age = age
		self.f = open('a.txt', 'r')

	def __str__(self):
		return '%s|%s' % (self.name, self.age)


obj = Student('judy', 18)
print(obj) #列印obj這個物件時,自動觸發__str__

二、刪除內容時觸發的內建方法

		# __del__

class Student:
	def __init__(self, name, age):
		self.name = name
		self.age = age
		self.f = open('a.txt', 'r')

	def __del__(self):
		print('當刪除屬性或方法的時候觸發執行')


obj = Student('judy', 18)

del obj.name
# 有兩種方法會觸發__del__執行
方式1:主動刪除
方式2:程式結束後清理記憶體時
如上面程式碼的1處,程式結束後,會清理記憶體空間,但是檔案不會關閉,此時就可以在__del__方法下面寫上關閉檔案的命令。

三、關於with上下文管理協議
with的執行原理

在檔案操作時,並不是不需要寫檔案的關閉,而是檔案的關閉操作在 with 的上下文管理器中的協議方法裡已經寫好了。當檔案操作執行完成後, with語句會自動呼叫上下文管理器裡的關閉語句來關閉檔案資源。

上下文管理器

ContextManager ,上下文是 context 直譯的叫法,在程式中用來表示程式碼執行過程中所處的前後環境。上下文管理器中有 enterexit 兩個方法,以with為例子,enter 方法會在執行 with 後面的語句時執行,一般用來處理操作前的內容。比如一些建立物件,初始化等;exit 方法會在 with 內的程式碼執行完畢後執行,一般用來處理一些善後收尾工作,比如檔案的關閉,資料庫的關閉等。

class Myopen:
	def __init__(self, path, mode):
		self.path = path
		self.mode = mode

	def __enter__(self):
		print('程式碼執行到__enter__')
		self.f = open(self.path, self.mode)
		return self.f

	def __exit__(self, exc_type, exc_val, exc_tb):
		print('程式碼執行到__exit__')
		self.f.close()


with Myopen('test.txt', 'w') as f:
	f.write('hello,judy')

程式碼執行結果:

	程式碼執行到__enter__
操作成功
程式碼執行到__exit__

檔案寫入操作執行完以後,自動呼叫了__exit__方法
__exit__方法的引數:
exc_type:異常型別
exc_va:異常值
exc_tb:異常回溯追蹤

class Mycount:
	def __init__(self, a, b):
		self.a = a
		self.b = b

	def __enter__(self):
		print('程式碼執行到__enter__')
		return self

	def __exit__(self, exc_type, exc_val, exc_tb):
		print('程式碼執行到__exit__')
		if exc_type==None:
			print('沒問題')
		else:
			print('Type:',exc_type)
			print('Value:', exc_val)
			print('TraceBack:', exc_tb)

	def my_div(self):
		res=self.a/self.b
		return res

with Mycount(1,0) as f:
	print(f.my_div())

執行結果:

程式碼執行到__enter__
程式碼執行到__exit__
Type: <class 'ZeroDivisionError'>
Value: division by zero
TraceBack: <traceback object at 0x7fd42edeeb08>

四、物件加括號可以觸發的方法

# __call__

如果一個物件定義了此方法,則該物件可以模擬函式的行為

class Foo:
	def __call__(self, x):
		print('找到x了 x:', x)


f = Foo()
f(1)

執行結果:

找到x了 x: 1

反射

class Student:
	def __init__(self, name, age):
		self.name = name
		self.age = age
		self.f = open('a.txt', 'r')

	def __str__(self):
		return '%s|%s' % (self.name, self.age)


obj = Student('judy', 18)

print(hasattr(obj, 'name'))  # 判斷obj是否有這個屬性
res = getattr(obj, 'name') #用字串呼叫屬性
print(res)
setattr(obj, 'name', 'mary') #用字串更改屬性
print(obj.name)
delattr(obj, 'name') #用字串刪除屬性

有句話說,python裡一切皆物件,所以反射方法不止可以用在物件身上,也可以用在類,甚至模組上。