2015-08-14 4 views
6

Что такое вещий способ PEP-8-римент, такие как с утверждением:Сохранение 80-кратного маржа надолго с заявлением?

with tempfile.NamedTemporaryFile(prefix='malt_input.conll.', dir=self.working_dir, mode='w', delete=False) as input_file, tempfile.NamedTemporaryFile(prefix='malt_output.conll.', dir=self.working_dir, mode='w', delete=False) as output_file: 
    pass 

Я мог бы это сделать, но так как TempFile I/O не с with заявления, делает это автоматически закрывается после того, как с ? Это вещий ?:

intemp = tempfile.NamedTemporaryFile(prefix='malt_input.conll.', dir=self.working_dir, mode='w', delete=False) 

outtemp = tempfile.NamedTemporaryFile(prefix='malt_output.conll.', dir=self.working_dir, mode='w', delete=False) 

with intemp as input_file, outtemp as output_file: 
    pass 

Или я мог бы использовать косые:

with tempfile.NamedTemporaryFile(prefix='malt_input.conll.', 
dir=self.working_dir, mode='w', delete=False) as input_file, \ 
tempfile.NamedTemporaryFile(prefix='malt_output.conll.', 
dir=self.working_dir, mode='w', delete=False) as output_file: 
    pass 

Но что PEP8 соблюдай состоянии? Это питонов?

+1

В разделе [PEP8] (https://www.python.org/dev/peps/pep-0008/#maximum-line-length) имеется раздел о максимальных длинах строк – GP89

+1

[Beyond PEP8] (https: // www.youtube.com/watch?v=wf-BqAjZb8M)! – mkrieger1

+1

Возможный дубликат [Как разбить длинный оператор с помощью python] (http://stackoverflow.com/questions/16080049/how-to-break-a-long-with-statement-in-python) – mkrieger1

ответ

3

PEP 0008 does say it's ok использовать обратную косую черту для линии with.

Обратные косые черты все еще могут быть уместны время от времени. Например, long, multiple с -statements не могут использовать неявное продолжение, поэтому обратная косая черта приемлема.

Хотя рекомендует им отступы, так что ваша линия должна быть такой:

with tempfile.NamedTemporaryFile(prefix='malt_input.conll.', 
     dir=self.working_dir, mode='w', delete=False) as input_file, \ 
     tempfile.NamedTemporaryFile(prefix='malt_output.conll.', 
     dir=self.working_dir, mode='w', delete=False) as output_file: 
    pass 

Это рекомендуется держать его отступом отчетливо различное количество пространства на следующий блок кода, так что понятнее где заканчивается строка с и начинается блок.

Однако вы на самом деле не необходимости использовать косую черту, если вы заключите параметры в скобках

with (tempfile.NamedTemporaryFile(prefix='malt_input.conll.', 
     dir=self.working_dir, mode='w', delete=False)) as input_file, (
     tempfile.NamedTemporaryFile(prefix='malt_output.conll.', 
     dir=self.working_dir, mode='w', delete=False)) as output_file: 
    pass 

Это действительно зависит от вашего точного расположения предложения, конечно, и ваш пробег может варьироваться от того, имея кронштейн в конце строки лучше, чем обратная косая черта.

1

PEP-8 фактически приведены примеры двух подобных ситуаций:

Пример 1 (выглядит наиболее применимо, так как он использует with заявления):

with open('/path/to/some/file/you/want/to/read') as file_1, \ 
    open('/path/to/some/file/being/written', 'w') as file_2: 
    file_2.write(file_1.read()) 

Пример 2:

class Rectangle(Blob): 

    def __init__(self, width, height, 
       color='black', emphasis=None, highlight=0): 

Это выглядит как косые черты - это допустимый способ обращения с этим (но в конечном итоге лишний, если вы скопируете параметры файла в круглые скобки).

3

PEP 8 не слишком понятно об этом. Он упоминает только with заявления раз за исключение, когда backslashe продолжений в порядке:

Обратных косые все еще могут быть целесообразными в разы.Например, длинный, многократная с -statements не может использовать неявное продолжение, поэтому обратные косые являются приемлемыми:

with open('/path/to/some/file/you/want/to/read') as file_1, \ 
    open('/path/to/some/file/being/written', 'w') as file_2: 
    file_2.write(file_1.read()) 

способом преодолеть эту проблему будет действительно сначала сделать вызов функции, которая возвращает менеджер контекста, а затем просто использовать это непосредственно, как вы уже предложили в вашем вопросе:

file_1 = open('/path/to/some/file/you/want/to/read') 
file_2 = open('/path/to/some/file/being/written', 'w') 

with file_1, file_2: 
    file_2.write(file_1.read()) 

Это прекрасно работает (потому что with заявление будет просто вызывать методы из контекста менеджера, независимо от того, откуда она пришла), а также закрывает ручки правильно ,

Однако это явно запрещено в PEP 8:

менеджеры Контекст должен вызываться через отдельные функции или методы, когда они делают что-то другое, чем приобретать и освободить ресурсы. Не Например:

Да:

with conn.begin_transaction(): 
    do_stuff_in_transaction(conn) 

№:

with conn: 
    do_stuff_in_transaction(conn) 

Последний пример не дает никакой информации, указывающей, что __enter__ и __exit__ методы делают нечто иное, чем закрыть соединение после транзакции. В этом случае важно быть явным.

Таким образом, в конце концов, кажется, нет никакого реального решения, которое позволило по PEP 8. И в этот момент, я бы сказал, что это прекрасно, чтобы «нарушить его» и идти против него: Это просто стиль руководство.

В то время как это предлагает много хороших правил, есть также много ситуаций, в которых просто не имеет смысла следовать им строго. Я бы сказал, что ваш пример использования косой черты едва читаемый, и вы, вероятно, можете прочитать это намного лучше, если бы вы позволили более длинным строки и просто сломали линию один раз в контекст менеджер:

with tempfile.NamedTemporaryFile(prefix='malt_input.conll.', dir=self.working_dir, mode='w', delete=False) as input_file, \ 
    tempfile.NamedTemporaryFile(prefix='malt_output.conll.', dir=self.working_dir, mode='w', delete=False) as output_file: 
    pass 

Да, вам может понадобиться для прокрутки для этого, но по крайней мере вы можете очень четко видеть, что происходит.

Другой альтернативой было бы на самом деле инициализировать объекты непосредственно перед with:

malt_input = tempfile.NamedTemporaryFile(prefix='malt_input.conll.', dir=self.working_dir, mode='w', delete=False) 
malt_output = tempfile.NamedTemporaryFile(prefix='malt_output.conll.', dir=self.working_dir, mode='w', delete=False) 
with malt_input as input_file, malt_output as output_file: 
    pass 

Поскольку вы делаете это непосредственно перед with, оно должно быть приемлемым исключение из правила PEP 8 здесь. В конце концов, это улучшает читаемость, и это важно.

КПП. обратите внимание, что диспетчер контекста не может возвращать self по адресу __enter__, поэтому вы должны использовать синтаксис as, чтобы присвоить возвращаемое значение диспетчера контекста переменной.


Наконец, один другой вариант, который будет работать на вашей конкретной ситуации, было бы обернуть вызов в отдельную функцию:

def namedTemp(prefix): 
    return tempfile.NamedTemporaryFile(prefix=prefix, 
     dir=self.working_dir, mode='w', delete=False) 

with namedTemp('malt_input.conll.') as input_file, \ 
    namedTemp('malt_output.conll.') as output_file: 
    pass 

Так в основном, абстрактные все прочь, так что with заявление снова становится читаемым.

+1

О, a ниспровергаемый фанатом PEP 8? – poke

+0

PEP8 фанатик, хороший! – alvas