Lập trình hướng đối tượng trong python datacamp github

"self" được trình thông dịch gán cho đối tượng hiện tại khi một phương thức được gọi và trình thông dịch mong đợi đối số đầu tiên của mỗi phương thức sẽ tính đến điều này

  • Ghi đè là thay đổi hoặc thay thế một phương thức của lớp cha bằng một phương thức mới [có cùng tên] trong lớp con. Không cần cú pháp đặc biệt để làm điều này;

  • Hàm super[] trả về đối tượng như một thể hiện của lớp cha, cho phép chúng ta gọi trực tiếp phương thức cha

  • đa thừa kế. Một lớp con kế thừa từ nhiều hơn một lớp cha có thể truy cập chức năng từ cả hai lớp đó. Hình thức đa thừa kế đơn giản và hữu ích nhất được gọi là mixin. Một mixin nói chung là một siêu lớp không tồn tại riêng mà được kế thừa bởi một số lớp khác để cung cấp chức năng bổ sung

  • # Example
    class Contact:
    	#all_contacts = []
    	all_contacts = ContactList[]
    	
    	def __init__[self, name, email]:
    		self.name = name
    		self.email = email
    		#Contact.all_contacts.append[self]
    		self.all_contacts.append[self]
            
     class MailSender:
    	def send_mail[self, message]:
    		print["sending mail to " + self.email]
            
    # multiple inheritance
    class EmailableContact[Contact, MailSender]:
    	pass

    Cú pháp đa thừa kế trông giống như một danh sách tham số trong định nghĩa lớp. Thay vì bao gồm một lớp cơ sở bên trong dấu ngoặc đơn, chúng tôi bao gồm hai [hoặc nhiều hơn] được phân tách bằng dấu phẩy

    >>>e = EmailableContact["Test user ", "testuser@example.net"]
    >>>e.send_mail["hello, test email here"]
    Sending mail to testuser@example.net
    

    • Đa kế thừa hoạt động tốt khi trộn các phương thức từ các lớp khác nhau, nhưng sẽ rất lộn xộn khi chúng ta phải làm việc với các phương thức gọi trên lớp cha. Vì có nhiều lớp cha. Làm thế nào để chúng ta biết cái nào để gọi?

    Vấn đề kim cương

    • Nếu chúng ta có hai phương thức init gốc mà cả hai đều cần được khởi tạo và chúng cần được khởi tạo với các đối số khác nhau. làm sao chúng ta làm việc đó bây giờ?

    class Addressholder:
    	def __init__[self, street, city, state, code]:
    		self.street = street
    		self.city = city
    		self.state = state
    		self.code = code
    	
    class Friend[Contact, Addressholder]:
    	def __init__[self, name, email, phone, street, city, state, code]:
    		Contact.__init__[self, name, email]
    		AddressHolder.__init__[self, street, city, state, code]
    		self.phone = phone

    Trong ví dụ này, chúng ta gọi trực tiếp hàm init trên mỗi lớp cha và chuyển đối số self một cách rõ ràng. Ví dụ này hoạt động về mặt kỹ thuật; chúng ta có thể truy cập các biến khác nhau trực tiếp trên lớp. Nhưng có một vài vấn đề

    1. Có khả năng một siêu lớp không được khởi tạo nếu chúng ta bỏ qua việc gọi trình khởi tạo một cách rõ ràng

    2. Khả năng siêu lớp được gọi nhiều lần, do tổ chức của hệ thống phân cấp lớp. Sơ đồ thừa kế bên dưới

    Phương thức init từ lớp Friend trước tiên gọi init trên Contact để khởi tạo hoàn toàn siêu lớp đối tượng [tất cả các lớp bắt nguồn từ obejct]. Sau đó, Friend gọi lệnh init trên AddressHolder, lệnh này ngầm khởi tạo lại siêu lớp đối tượng. Lớp cha đã được thiết lập hai lần. Hãy tưởng tượng cố gắng kết nối với cơ sở dữ liệu hai lần cho mọi yêu cầu. Lớp cơ sở chỉ nên được gọi một lần

    • Về mặt kỹ thuật, thứ tự mà các phương thức có thể được gọi có thể được điều chỉnh nhanh chóng bằng cách sửa đổi thuộc tính mro [Thứ tự phân giải phương thức] của lớp

    Hãy xem xét một ví dụ thứ hai minh họa vấn đề này rõ ràng hơn. Ở đây có một lớp cơ sở có một phương thức tên là call_me. Hai lớp con ghi đè phương thức đó và sau đó một lớp con khác mở rộng cả hai lớp này bằng cách sử dụng đa kế thừa. Điều này được gọi là kế thừa kim cương vì hình dạng kim cương của sơ đồ lớp

    Kim cương là thứ khiến cho việc thừa kế trở nên khó khăn. Về mặt kỹ thuật, tất cả đa kế thừa trong Python3 là kế thừa kim cương, bởi vì tất cả các lớp đều kế thừa từ đối tượng

    class MyClass:
    
    	@classmethod                #>>e = EmailableContact["Test user ", "testuser@example.net"]
    >>>e.send_mail["hello, test email here"]
    Sending mail to testuser@example.net
    
    17 và
    class SavingsAccount[BankAccount]:
    	def __init__[self, balance, interest_rate]:
    		BankAccount.__init__[self, balance]
    		self.interest_rate = interest_rate
    
    	# new functionality
    	def compute_interest[self, n_periods=1]:
    		return self.balance * [[1 + self.interest_rate] ** n_periods - 1]
    6 theo quy ước. Trả về một boolean
  • Khi so sánh hai đối tượng của một lớp tùy chỉnh bằng ==, Python theo mặc định chỉ so sánh các tham chiếu đối tượng, không phải dữ liệu chứa trong các đối tượng. Để ghi đè hành vi này, lớp có thể triển khai phương thức eq[] đặc biệt, phương thức này chấp nhận hai đối số -- đối tượng được so sánh -- và trả về Đúng hoặc Sai. Phương thức này sẽ được gọi ngầm khi hai đối tượng được so sánh
  • class MyClass:
    
    	@classmethod                #>>e = EmailableContact["Test user ", "testuser@example.net"]
    >>>e.send_mail["hello, test email here"]
    Sending mail to testuser@example.net
    
    74 sẽ trả về True, mặc dù chúng tôi đang so sánh số điện thoại với số tài khoản ngân hàng. Bạn nên kiểm tra lớp đối tượng được truyền cho phương thức eq[] để đảm bảo việc so sánh có ý nghĩa
  • Bây giờ chỉ so sánh các đối tượng của cùng một lớp BankAccount mới có thể trả về True. Một cách khác để đảm bảo rằng một đối tượng có cùng kiểu như bạn mong đợi là sử dụng hàm isinstance[obj, Class]. Điều này có thể hữu ích khi xử lý tính kế thừa, vì Python coi một đối tượng là một thể hiện của cả lớp cha và lớp con
  • So sánh và kế thừa

    • Điều gì xảy ra khi một đối tượng được so sánh với một đối tượng của lớp con?

    class MyClass:
    
    	@classmethod                #>>e = EmailableContact["Test user ", "testuser@example.net"]
    >>>e.send_mail["hello, test email here"]
    Sending mail to testuser@example.net
    
    10

    • Chúng ta phải luôn định nghĩa ít nhất một trong các phương thức biểu diễn chuỗi cho đối tượng out để đảm bảo rằng người sử dụng lớp của chúng ta có thể lấy thông tin quan trọng về đối tượng một cách dễ dàng

    ngoại lệ

    xử lý ngoại lệ

    • sử dụng mã
      class MyClass:
      
      	@classmethod                #>>e = EmailableContact["Test user ", "testuser@example.net"]
      >>>e.send_mail["hello, test email here"]
      Sending mail to testuser@example.net
      
      12

      Bắt ngoại lệ tùy chỉnh

      >>>e = EmailableContact["Test user ", "testuser@example.net"]
      >>>e.send_mail["hello, test email here"]
      Sending mail to testuser@example.net
      
      13

      Xử lý phân cấp ngoại lệ

      • Tốt hơn là liệt kê các khối ngoại trừ theo thứ tự cụ thể tăng dần, tôi. e. con trước cha mẹ, nếu không thì ngoại lệ con sẽ được gọi trong khối cha ngoại trừ

      Thiết kế cho sự kế thừa và đa hình

      đa hình

      • Sử dụng giao diện thống nhất để thao tác trên các đối tượng thuộc các lớp khác nhau

      • Lớp BankAccount, SavingsAccount vàCheckingAccount có phương thức rút tiền nhưng phương thức ChecingAccount đang thực thi mã khác

      Tất cả những gì quan trọng là một giao diện

      • Giả sử chúng ta định nghĩa một chức năng để rút cùng một lượng tiền từ toàn bộ danh sách tài khoản cùng một lúc. Hàm không quan tâm liệu các đối tượng được truyền cho nó làCheckingAccount, SavingsAccount hay hỗn hợp. Tất cả vấn đề là họ có một phương thức rút tiền chấp nhận một đối số đủ để hàm hoạt động
      • Nó không kiểm tra việc rút tiền nào nên gọi là bản gốc hay bản sửa đổi. Khi phương thức rút tiền thực sự được gọi là python sẽ tự động kéo đúng phương thức
      • Rút tiền đã sửa đổi khi Tài khoản kiểm tra đang được xử lý và phương thức cơ bản khi Tài khoản tiết kiệm hoặc tài khoản thông thường được gọi

      >>>e = EmailableContact["Test user ", "testuser@example.net"]
      >>>e.send_mail["hello, test email here"]
      Sending mail to testuser@example.net
      
      14

      • # Example
        class Contact:
        	#all_contacts = []
        	all_contacts = ContactList[]
        	
        	def __init__[self, name, email]:
        		self.name = name
        		self.email = email
        		#Contact.all_contacts.append[self]
        		self.all_contacts.append[self]
                
         class MailSender:
        	def send_mail[self, message]:
        		print["sending mail to " + self.email]
                
        # multiple inheritance
        class EmailableContact[Contact, MailSender]:
        	pass
        2 không cần kiểm tra đối tượng để biết phải gọi
        # Example
        class Contact:
        	#all_contacts = []
        	all_contacts = ContactList[]
        	
        	def __init__[self, name, email]:
        		self.name = name
        		self.email = email
        		#Contact.all_contacts.append[self]
        		self.all_contacts.append[self]
                
         class MailSender:
        	def send_mail[self, message]:
        		print["sending mail to " + self.email]
                
        # multiple inheritance
        class EmailableContact[Contact, MailSender]:
        	pass
        3 nào

      Nguyên tắc thay thế Liskov

      • Có một nguyên tắc thiết kế hướng đối tượng cơ bản về thời điểm và cách sử dụng tính kế thừa đúng cách được gọi là nguyên tắc thay thế Liskov. `Lớp cơ sở có thể hoán đổi với bất kỳ lớp con nào của nó mà không làm thay đổi bất kỳ thuộc tính nào của chương trình
      • Điều đó có nghĩa là bất cứ nơi nào
        # Example
        class Contact:
        	#all_contacts = []
        	all_contacts = ContactList[]
        	
        	def __init__[self, name, email]:
        		self.name = name
        		self.email = email
        		#Contact.all_contacts.append[self]
        		self.all_contacts.append[self]
                
         class MailSender:
        	def send_mail[self, message]:
        		print["sending mail to " + self.email]
                
        # multiple inheritance
        class EmailableContact[Contact, MailSender]:
        	pass
        4 hoạt động, thì
        # Example
        class Contact:
        	#all_contacts = []
        	all_contacts = ContactList[]
        	
        	def __init__[self, name, email]:
        		self.name = name
        		self.email = email
        		#Contact.all_contacts.append[self]
        		self.all_contacts.append[self]
                
         class MailSender:
        	def send_mail[self, message]:
        		print["sending mail to " + self.email]
                
        # multiple inheritance
        class EmailableContact[Contact, MailSender]:
        	pass
        5 cũng sẽ hoạt động. cho e. g Hàm
        # Example
        class Contact:
        	#all_contacts = []
        	all_contacts = ContactList[]
        	
        	def __init__[self, name, email]:
        		self.name = name
        		self.email = email
        		#Contact.all_contacts.append[self]
        		self.all_contacts.append[self]
                
         class MailSender:
        	def send_mail[self, message]:
        		print["sending mail to " + self.email]
                
        # multiple inheritance
        class EmailableContact[Contact, MailSender]:
        	pass
        6 hoạt động bất kể loại tài khoản nào được sử dụng

      LSP vi phạm

      • không tương thích cú pháp.
        # Example
        class Contact:
        	#all_contacts = []
        	all_contacts = ContactList[]
        	
        	def __init__[self, name, email]:
        		self.name = name
        		self.email = email
        		#Contact.all_contacts.append[self]
        		self.all_contacts.append[self]
                
         class MailSender:
        	def send_mail[self, message]:
        		print["sending mail to " + self.email]
                
        # multiple inheritance
        class EmailableContact[Contact, MailSender]:
        	pass
        7 yêu cầu 1 tham số, nhưng
        # Example
        class Contact:
        	#all_contacts = []
        	all_contacts = ContactList[]
        	
        	def __init__[self, name, email]:
        		self.name = name
        		self.email = email
        		#Contact.all_contacts.append[self]
        		self.all_contacts.append[self]
                
         class MailSender:
        	def send_mail[self, message]:
        		print["sending mail to " + self.email]
                
        # multiple inheritance
        class EmailableContact[Contact, MailSender]:
        	pass
        8 yêu cầu 2
      • Phân lớp tăng cường điều kiện đầu vào.
        # Example
        class Contact:
        	#all_contacts = []
        	all_contacts = ContactList[]
        	
        	def __init__[self, name, email]:
        		self.name = name
        		self.email = email
        		#Contact.all_contacts.append[self]
        		self.all_contacts.append[self]
                
         class MailSender:
        	def send_mail[self, message]:
        		print["sending mail to " + self.email]
                
        # multiple inheritance
        class EmailableContact[Contact, MailSender]:
        	pass
        7 chấp nhận bất kỳ số lượng nào, nhưng
        # Example
        class Contact:
        	#all_contacts = []
        	all_contacts = ContactList[]
        	
        	def __init__[self, name, email]:
        		self.name = name
        		self.email = email
        		#Contact.all_contacts.append[self]
        		self.all_contacts.append[self]
                
         class MailSender:
        	def send_mail[self, message]:
        		print["sending mail to " + self.email]
                
        # multiple inheritance
        class EmailableContact[Contact, MailSender]:
        	pass
        8 cho rằng số lượng đó bị hạn chế
      • Phân lớp làm suy yếu điều kiện đầu ra.
        # Example
        class Contact:
        	#all_contacts = []
        	all_contacts = ContactList[]
        	
        	def __init__[self, name, email]:
        		self.name = name
        		self.email = email
        		#Contact.all_contacts.append[self]
        		self.all_contacts.append[self]
                
         class MailSender:
        	def send_mail[self, message]:
        		print["sending mail to " + self.email]
                
        # multiple inheritance
        class EmailableContact[Contact, MailSender]:
        	pass
        7 chỉ có thể để lại số dư dương hoặc gây ra lỗi,
        # Example
        class Contact:
        	#all_contacts = []
        	all_contacts = ContactList[]
        	
        	def __init__[self, name, email]:
        		self.name = name
        		self.email = email
        		#Contact.all_contacts.append[self]
        		self.all_contacts.append[self]
                
         class MailSender:
        	def send_mail[self, message]:
        		print["sending mail to " + self.email]
                
        # multiple inheritance
        class EmailableContact[Contact, MailSender]:
        	pass
        8 có thể để lại số dư âm
      • Thay đổi các thuộc tính bổ sung trong phương thức của lớp con không được thay đổi trong lớp cơ sở
      • Ném các ngoại lệ bổ sung trong phương thức của lớp con mà lớp cơ sở không ném

      Không LSP - Không kế thừa

      • Nếu hệ thống phân cấp lớp làm hỏng LSP, thì chúng ta không nên sử dụng tính kế thừa bcz, nó có khả năng hoạt động mã theo những cách không thể đoán trước

    Chủ Đề