Когда я определяю функции, в каком порядке я должен поместить параметры? - PullRequest
7 голосов
/ 19 января 2011

Мне часто трудно решить, и я непоследователен.Есть ли какие-то правила, которым я мог бы следовать?

Например:

def remove_except(haystack, needle, exclude_value):
    for key in hackstack:
        if key in needle and haystack[key] != exclude_value:
            hackstack.pop(key)

может быть легко:

def remove_except(needle, exclude_value, haystack):
    for key in hackstack:
        if key in needle and haystack[key] != exclude_value:
            hackstack.pop(key)

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

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

Ответы [ 7 ]

3 голосов
/ 19 января 2011

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

Теперь, с Python и JavaScript, вы можете использовать ориентацию объекта, чтобы исключить хотя бы стог сена, потому что стог сена будет (или, по крайней мере, может быть) объектом, который вы действуя и так, как вы это делаете, будет диктоваться языком (например, delete haystack[needle]; [JavaScript для удаления свойства из объекта] или del haystack[needle] [Python для удаления словарной статьи]). C не является объектно-ориентированным (C ++, D, Objective-C и некоторые другие производные), поэтому вам нужно искать там соглашение.

Субъективно говоря , по моему опыту, haystack обычно на первом месте, но это может быть просто мой опыт. Точно так же мое субъективное мнение состояло бы в том, что exclude_value будет последним (то есть haystack, needle, exclude_value), потому что будут другие операции, которые будут принимать haystack, needle, something_else & mdash; но это просто мнение.

1 голос
/ 19 января 2011

Точно так же, как некоторая вспомогательная информация для хора «сначала поставьте стог сена», в данном случае в основном для JavaScript : когда вы думаете о том, какой параметр является «самым важным», или какой«стог сена», он (может) помогает подумать о том, какой параметр, вероятно, будет отличаться между вызовами, а какой может измениться.В вашем примере, «игла», вероятно, довольно изменчива от вызова к вызову, в то время как «стог сена» может всегда или почти всегда быть одним и тем же.

Ну, если это так, то это обычноиспользовать такую ​​утилиту только для одного конкретного объекта - метод «bind ()», доступный в новых средах JavaScript (на прототипе Function) или добавленный библиотекой, такой как Prototype или Functional, может быть действительно полезным:

function whatever(haystack, needle) {
  // ...
};

var myHaystack = new Haystack( /* ... */ );

var myHaystackWhatever = whatever.bind(null, myHaystack);

Теперь функцию «myHaystackWhwhat» можно использовать следующим образом:

var result = myHaystackWhatever(someNeedle);

Это может показаться тривиальным, но в функциональном языке, таком как JavaScript, возможность легко и надежно создавать новую функцию как вариантна существующем это очень удобно, сохраняя много путаницы при наборе текста и парсинг-скобках.

Дело в том, что такие средства, как «связывание», особенно в JavaScript, который имеет чисто основанную на порядке привязку значений вызовак формальным параметрам вы привязываете фиксированные значения слева направо.Таким образом, если ваш самый левый параметр, скорее всего, представляет собой миллиард разных вещей, то «bind ()» не слишком интересен.(Функциональная библиотека JavaScript имеет способ связывания других параметров, причем не только слева направо, но и довольно экзотично и странно и, на мой взгляд, в основном интересно в качестве примера кодирования.)

1 голос
/ 19 января 2011

Это очень зависит от вас. Если вы пишете одну функцию, которая не похожа ни на что другое в содержащем, скажем, проекте, тогда обязательные / важные параметры идут первыми, а необязательные / неважные - после. Язык, который вы используете, может влиять на выбор; Python позволяет указывать необязательные именованные параметры или ключевые аргументы, но они должны следовать позиционным параметрам.

Если вы пишете набор похожих функций для API, согласованность становится более важной. Используя пример сена, вы можете получить

def insert(haystack, needle)
def remove(haystack, needle)
def remove_except(haystack, needle, exclude_value)
def copy(haystack, haystack2)

, где стог сена идет первым, потому что он является ключевым параметром для всех перечисленных методов и имеет

def remove(needle, haystack)
def remove_except(haystack, needle, exclude_value)

будет выглядеть странно (но, конечно, все равно будет работать).

Если вы используете объектно-ориентированный язык и вы пишете целый ряд функций, которые совместно используют параметр, вы, вероятно, подумаете о том, чтобы сделать это объектом и методами функций, которые работают с этим объектом, но это, вероятно, выходит за рамки вопрос.

Для выбранного языка найдите какой-нибудь хорошо используемый код и изучите его. Если вы используете Python, взгляните на стандартные библиотеки. Для Javascript jQuery может быть хорошим.

1 голос
/ 19 января 2011

Я считаю, что конвенция слева направо - самая важная, а не самая важная.так что для вашего примера я бы сделал (иголка, стог сена, exclude_value).игла является наиболее важной в этом случае, потому что это определяющая информация о вызове.тот же стог сена может быть использован в другом вызове с другой иглой.Кажется, что Exclude_value может быть необязательным.

0 голосов
/ 19 января 2011

Помимо «неформальных» правил согласованности или «от наиболее важных до наименее важных», в Python существуют также некоторые языковые правила:

Определение функции может содержать (в таком порядке):

  • позиционные аргументы (т.е. обязательные параметры без значения по умолчанию),
  • аргументы ключевых слов (т. Е. Необязательные аргументы, в которых значение по умолчанию указывается при определении функции),
  • переменные аргументы (т.е. неопределенное количество неназванных параметров) и / или
  • переменные аргументы ключевых слов (т.е. неопределенное количество свободно «именуемых» аргументов ключевых слов)

Так что вы можете написать

def myfunc(x, y, z=0, truncate=True, *args, **kwargs):
    do_something()

, который затем можно было бы назвать

myfunc(1,2)
myfunc(1,2,3,False)
myfunc(1,2,3,True, "some more args", mykeyword="keyword arg")

Но вы не можете определить функцию следующим образом:

def wontwork(x=0, y, z):
def wontworkeither(*args, debug=True)

Это подробно описано в Python Tutorial .

0 голосов
/ 19 января 2011

В вашем примере я бы начал с того, что объект оперируют или выполняют действие. Затем самые необходимые параметры в первую очередь. Так что Хейстек, иголка, исключенная стоимость. Если существует вероятность того, что другая версия функции будет удалена с некоторыми параметрами (например, без исключенного значения), они обычно идут в конце. Я сейчас думаю на C, но ваш пример - python, так что есть возможность обработки необязательных параметров или параметров по умолчанию ...

0 голосов
/ 19 января 2011

Полагаю, это зависит только от вас.

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