Làm thế nào để phá vỡ một dòng các phương thức xích trong Python?


137

Tôi có một dòng mã sau đây (đừng đổ lỗi cho việc đặt tên cho các quy ước, chúng không phải là của tôi):

subkeyword = Session.query(
    Subkeyword.subkeyword_id, Subkeyword.subkeyword_word
).filter_by(
    subkeyword_company_id=self.e_company_id
).filter_by(
    subkeyword_word=subkeyword_word
).filter_by(
    subkeyword_active=True
).one()

Tôi không thích nó trông như thế nào (không quá dễ đọc) nhưng tôi không có ý tưởng nào tốt hơn để giới hạn các dòng trong 79 ký tự trong tình huống này. Có cách nào tốt hơn để phá vỡ nó (tốt nhất là không có dấu gạch chéo ngược)?

Câu trả lời:


255

Bạn có thể sử dụng dấu ngoặc đơn bổ sung:

subkeyword = (
        Session.query(Subkeyword.subkeyword_id, Subkeyword.subkeyword_word)
        .filter_by(subkeyword_company_id=self.e_company_id)
        .filter_by(subkeyword_word=subkeyword_word)
        .filter_by(subkeyword_active=True)
        .one()
    )

Tôi cũng thích nó nhất. Không thêm mã và nó không có dấu gạch chéo ngược.
Juliusz Gonera

22
Không chắc chắn những gì biện minh cho việc thụt thêm ở đây; Tôi nghĩ rằng giải pháp này cũng đọc được với các đường treo được thụt vào chỉ một lần và dấu paren không hoàn toàn.
Carl Meyer

4
Theo tôi, thụt đôi là hữu ích ở đây vì nó khác biệt trực quan với một khối thụt lề bình thường. Khi được bao quanh bởi các mã khác, điều này làm cho nó rõ ràng hơn rằng nó là một dòng duy nhất được bọc.
sth

1
Câu trả lời tốt nhất, về mặt sử dụng parens. Như được đề cập trong một nhận xét của Shanimal trong một câu trả lời khác, sử dụng tiếp tục dòng ngụ ý thông qua dấu ngoặc đơn thực sự là PEP 8 được ưa thích so với ký tự tiếp tục ``
kevlarr

Tôi thích dấu gạch chéo ngược. Dấu ngoặc đơn không phải là một gợi ý cho tất cả các tình huống. Ví dụ, nó không hoạt động với toán tử gán. Hãy tưởng tượng bạn muốn ngắt dòng trong chuỗi này:foo.set_default('bar', {}).set_default('spam', {}).set_default('eggs', {})['lol'] = 'yeah'
loutre

56

Đây là trường hợp một ký tự tiếp tục dòng được ưa thích để mở dấu ngoặc đơn. Nhu cầu về kiểu này trở nên rõ ràng hơn khi các tên phương thức trở nên dài hơn và khi các phương thức bắt đầu lấy các đối số:

subkeyword = Session.query(Subkeyword.subkeyword_id, Subkeyword.subkeyword_word) \
                    .filter_by(subkeyword_company_id=self.e_company_id)          \
                    .filter_by(subkeyword_word=subkeyword_word)                  \
                    .filter_by(subkeyword_active=True)                           \
                    .one()

PEP 8 có ý định được giải thích với thước đo của lẽ thường và con mắt cho cả thực tế và đẹp. Hạnh phúc vi phạm bất kỳ hướng dẫn PEP 8 nào dẫn đến mã xấu hoặc khó đọc.

Điều đó đang được nói, nếu bạn thường xuyên thấy mình bất hòa với PEP 8, đó có thể là một dấu hiệu cho thấy có những vấn đề dễ đọc vượt qua sự lựa chọn khoảng trắng của bạn :-)


2
+1 trên dấu gạch chéo ngược và căn chỉnh các bộ lọc chuỗi trong trường hợp cụ thể này. Tình huống này cũng phát sinh ở Django và dễ đọc nhất theo cách này - nhưng trong bất kỳ tình huống nào khác, tôi cảm thấy các cụm từ được ngoặc đơn là vượt trội (không gặp phải vấn đề "có khoảng trắng sau dấu gạch chéo ngược của tôi không?"). Điều đó nói rằng, ngoặc đơn cụm từ có thể được sử dụng để đạt được hiệu quả tương tự - nhưng nó đưa bạn vào chế độ đọc Lisp ở giữa đọc Python, mà tôi thấy bị chói tai.
zxq9

11
Tôi không thấy cách giải pháp này có khả năng đối phó tốt hơn "khi các tên phương thức trở nên dài hơn và khi các phương thức bắt đầu lấy đối số" hơn là "bao bọc bên ngoài" hoặc "ngắt dòng sau mỗi paren mở và trước mỗi paren đóng" các giải pháp. Trong thực tế, điều tồi tệ hơn là xử lý điều đó, vì (ít nhất là như được hiển thị ở đây), nó đòi hỏi phải thụt sâu hơn nhiều cho mỗi dây treo.
Carl Meyer

1
Quá nhiều thụt lề cho các cuộc gọi bộ lọc. Một tab hoặc 4 khoảng trắng sẽ là đủ ở đây. Đồng thời căn chỉnh của `` ... Bạn đã giữ phím không gian đó bao nhiêu giây? Nói chung tôi chống lại tất cả các cách, đòi hỏi bạn phải gõ phím không gian đó như không có ngày mai.
Zelphir Kaltstahl

2
fwiw, PEP8 đọc "Cách gói dòng dài ưa thích là sử dụng tiếp tục dòng ngụ ý của Python bên trong dấu ngoặc đơn, dấu ngoặc và dấu ngoặc. Các dòng dài có thể được chia thành nhiều dòng bằng cách gói biểu thức trong ngoặc đơn. Chúng nên được sử dụng theo cách sử dụng dấu gạch chéo ngược để tiếp tục dòng. " - Python.org Tiếp tục thảo luận khi dấu gạch chéo ngược có thể phù hợp
Shanimal

Tài liệu tham khảo tuyệt vời cho PEP8! Một vấn đề khó chịu ở đây với việc căn chỉnh tất cả các .filtercuộc gọi là nếu bạn thay đổi subkeywordthành sub_keyword, bây giờ bạn phải sửa lỗi thụt dòng của mỗi dòng chỉ vì bạn đã thay đổi tên biến. Không tốt khi phong cách thực sự cản trở khả năng bảo trì ...
kevlarr

15

Lựa chọn cá nhân của tôi sẽ là:

từ khóa phụ = Session.query (
    Subkeyword.subkeyword_id,
    Subkeyword.subkeyword_word,
).lọc bởi(
    subkeyword_company_id = self.e_company_id,
    subkeyword_word = subkeyword_word,
    subkeyword_active = Đúng,
).một()

1
Tôi đồng ý nếu có một vài tham số được truyền vào nhưng nó trông xấu khi các tham số 0 hoặc 1 là phổ biến. Ví dụ: gist.github.com/andybak/b23b6ad9a68c7e1b794d
Andy Baker

1
Vâng, phong cách đó có trường hợp thoái hóa (như bất kỳ phong cách). Tôi sẽ không phá vỡ tất cả các parens mở. Không ai trong số này làm tôi hạnh phúc, nhưng đây là một số trường hợp: gist.github.com/pkoch/8098c76614765750f769
pkoch

12

Chỉ cần lưu trữ kết quả / đối tượng trung gian và gọi phương thức tiếp theo trên nó, vd

q = Session.query(Subkeyword.subkeyword_id, Subkeyword.subkeyword_word)
q = q.filter_by(subkeyword_company_id=self.e_company_id)
q = q.filter_by(subkeyword_word=subkeyword_word)
q = q.filter_by(subkeyword_active=True)
subkeyword = q.one()

10
Điều này hoạt động tốt cho một cái gì đó giống như một truy vấn nhưng như một mô hình chung, tôi không chắc chắn lắm. Ví dụ: khi kết nối trong Beautiful Soup như thế nào team_members = soup.find(class_='section team').find_all('ul').find_all('li'), giá trị trả về từ mỗi .find(...)cuộc gọi chưa phù hợp với ý nghĩa của team_membersnó.
Taylor Edmiston

1
@TaylorEdmiston Bạn có thể có các tên khác nhau cho kết quả một phần của khóa học. Một cái gì đó như section = soup.find(class_='section team')team_members = section.find_all('ul').find_all('li').
Jeyekomon

4

Theo tài liệu tham khảo ngôn ngữ Python
Bạn có thể sử dụng dấu gạch chéo ngược.
Hoặc đơn giản là phá vỡ nó. Nếu một dấu ngoặc không được ghép nối, python sẽ không coi đó là một dòng. Và trong trường hợp như vậy, việc thụt dòng theo sau không thành vấn đề.


4

Đó là một chút giải pháp khác với những người khác cung cấp nhưng là một yêu thích của tôi vì đôi khi nó dẫn đến việc lập trình siêu tiện lợi.

base = [Subkeyword.subkeyword_id, Subkeyword_word]
search = {
    'subkeyword_company_id':self.e_company_id,
    'subkeyword_word':subkeyword_word,
    'subkeyword_active':True,
    }
subkeyword = Session.query(*base).filter_by(**search).one()

Đây là một kỹ thuật tốt đẹp để xây dựng các tìm kiếm. Đi qua một danh sách các điều kiện để khai thác từ mẫu truy vấn phức tạp của bạn (hoặc các khoản khấu trừ dựa trên chuỗi về những gì người dùng đang tìm kiếm), sau đó chỉ cần nổ từ điển vào bộ lọc.


1

Bạn dường như sử dụng SQLAlchemy, nếu nó đúng, sqlalchemy.orm.query.Query.filter_by()phương thức sẽ lấy nhiều đối số từ khóa, vì vậy bạn có thể viết như sau:

subkeyword = Session.query(Subkeyword.subkeyword_id,
                           Subkeyword.subkeyword_word) \
                    .filter_by(subkeyword_company_id=self.e_company_id,
                               subkeyword_word=subkeyword_word,
                               subkeyword_active=True) \
                    .one()

Nhưng nó sẽ tốt hơn:

subkeyword = Session.query(Subkeyword.subkeyword_id,
                           Subkeyword.subkeyword_word)
subkeyword = subkeyword.filter_by(subkeyword_company_id=self.e_company_id,
                                  subkeyword_word=subkeyword_word,
                                  subkeyword_active=True)
subkeuword = subkeyword.one()

+1 cho gợi ý SQLAlchemy filter_by (). Ví dụ này tốt cho ví dụ này, nhưng tôi thường sử dụng bộ lọc () thay vì chỉ chấp nhận 1 điều kiện.
Juliusz Gonera

1

Tôi thích thụt lề các đối số theo hai khối và câu lệnh theo một khối, như sau:

for image_pathname in image_directory.iterdir():
    image = cv2.imread(str(image_pathname))
    input_image = np.resize(
            image, (height, width, 3)
        ).transpose((2,0,1)).reshape(1, 3, height, width)
    net.forward_all(data=input_image)
    segmentation_index = net.blobs[
            'argmax'
        ].data.squeeze().transpose(1,2,0).astype(np.uint8)
    segmentation = np.empty(segmentation_index.shape, dtype=np.uint8)
    cv2.LUT(segmentation_index, label_colours, segmentation)
    prediction_pathname = prediction_directory / image_pathname.name
    cv2.imwrite(str(prediction_pathname), segmentation)
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.