Về gõ vịt :
Gõ vịt được hỗ trợ bởi thói quen không kiểm tra loại đối số trong các cơ quan phương thức và chức năng, dựa vào tài liệu, mã rõ ràng và kiểm tra để đảm bảo sử dụng đúng.
Về xác thực đối số (EAFP: Dễ dàng yêu cầu sự tha thứ hơn là sự cho phép). Một ví dụ thích nghi từ đây :
... nó được coi là nhiều pythonic hơn để làm:
def my_method(self, key):
try:
value = self.a_dict[member]
except TypeError:
# do something else
Điều này có nghĩa là bất kỳ ai khác sử dụng mã của bạn không phải sử dụng từ điển hoặc lớp con thực sự - họ có thể sử dụng bất kỳ đối tượng nào thực hiện giao diện ánh xạ.
Thật không may trong thực tế nó không đơn giản. Nếu thành viên trong ví dụ trên có thể là số nguyên thì sao? Số nguyên là bất biến - vì vậy việc sử dụng chúng làm khóa từ điển là hoàn toàn hợp lý. Tuy nhiên, chúng cũng được sử dụng để lập chỉ mục các đối tượng loại trình tự. Nếu thành viên tình cờ là một số nguyên thì ví dụ hai có thể cho qua danh sách và chuỗi cũng như từ điển.
Về lập trình quyết đoán :
Các xác nhận là một cách có hệ thống để kiểm tra xem trạng thái bên trong của chương trình có đúng như lập trình viên mong đợi hay không, với mục tiêu là bắt lỗi. Cụ thể, chúng tốt cho việc nắm bắt các giả định sai được đưa ra trong khi viết mã hoặc lạm dụng giao diện bởi một lập trình viên khác. Ngoài ra, họ có thể đóng vai trò là tài liệu nội tuyến ở một mức độ nào đó, bằng cách làm cho các giả định của lập trình viên trở nên rõ ràng. ("Rõ ràng là tốt hơn ngầm định.")
Các khái niệm được đề cập đôi khi mâu thuẫn, vì vậy tôi dựa vào các yếu tố sau khi chọn nếu tôi không thực hiện bất kỳ xác thực dữ liệu nào, xác thực mạnh hoặc sử dụng các xác nhận:
Xác nhận mạnh mẽ. Bằng cách xác nhận mạnh mẽ, tôi có nghĩa là nâng một Ngoại lệ tùy chỉnh (
ApiError
ví dụ). Nếu chức năng / phương thức của tôi là một phần của API công khai, tốt hơn hết là xác thực đối số để hiển thị thông báo lỗi tốt về loại không mong muốn. Bằng cách kiểm tra loại tôi không có nghĩa là chỉ sử dụngisinstance
, mà còn nếu đối tượng được thông qua hỗ trợ giao diện cần thiết (gõ vịt). Trong khi tôi ghi lại API và chỉ định loại dự kiến và người dùng có thể muốn sử dụng chức năng của tôi theo cách không mong muốn, tôi cảm thấy an toàn hơn khi kiểm tra các giả định. Tôi thường sử dụngisinstance
và nếu sau này tôi muốn hỗ trợ các loại hoặc vịt khác, tôi thay đổi logic xác thực.Lập trình quyết đoán. Nếu mã của tôi là mới, tôi sử dụng khẳng định rất nhiều. Lời khuyên của bạn về điều này là gì? Bạn có sau đó loại bỏ khẳng định từ mã?
Nếu chức năng / phương thức của tôi không phải là một phần của API, nhưng chuyển một số đối số của nó sang một mã khác không được tôi viết, nghiên cứu hoặc kiểm tra, tôi thực hiện rất nhiều khẳng định theo giao diện được gọi. Logic của tôi đằng sau điều này - tốt hơn là thất bại trong mã của tôi, sau đó ở đâu đó sâu hơn 10 cấp độ trong stacktrace với lỗi không thể hiểu được buộc phải gỡ lỗi rất nhiều và sau đó thêm khẳng định vào mã của tôi.
Nhận xét và lời khuyên về khi nào nên sử dụng hay không sử dụng xác nhận loại / giá trị, khẳng định? Xin lỗi vì không phải là công thức tốt nhất của câu hỏi.
Ví dụ, hãy xem xét hàm sau, Customer
mô hình khai báo SQLAlchemy ở đâu :
def add_customer(self, customer):
"""Save new customer into the database.
@param customer: Customer instance, whose id is None
@return: merged into global session customer
"""
# no validation here at all
# let's hope SQLAlchemy session will break if `customer` is not a model instance
customer = self.session.add(customer)
self.session.commit()
return customer
Vì vậy, có một số cách để xử lý xác nhận:
def add_customer(self, customer):
# this is an API method, so let's validate the input
if not isinstance(customer, Customer):
raise ApiError('Invalid type')
if customer.id is not None:
raise ApiError('id should be None')
customer = self.session.add(customer)
self.session.commit()
return customer
hoặc là
def add_customer(self, customer):
# this is an internal method, but i want to be sure
# that it's a customer model instance
assert isinstance(customer, Customer), 'Achtung!'
assert customer.id is None
customer = self.session.add(customer)
self.session.commit()
return customer
Khi nào và tại sao bạn sẽ sử dụng từng thứ này trong ngữ cảnh gõ vịt, kiểm tra kiểu, xác thực dữ liệu?