Единственная разница между create_file
и edit_file
- это функция, которую вы вызываете, чтобы получить значение для file_blob_sha
.Вы можете сделать вид, что create_file
вызвал функцию, которая возвратила None
(или любое другое значение по умолчанию для этого параметра, равное _file_data
).
Определите общую базовую функцию, которая принимает необходимую функцию в качестве аргумента.вместо жесткого кодирования его в тело create_file
или edit_file
.
def _base(self,
file_blob,
filename,
commit_message,
committer_info,
branch,
fn):
file_blob_sha = fn(branch, filename)
json_file_data = self._file_data(file_blob, commit_message, committer_info, branch, file_blob_sha)
content_url = '{}/{}'.format(self._github_content_url, filename)
response = self._request(content_url, method='PUT', data=json_file_data)
self._handle_errors(response)
(обратите внимание, что тело выглядит точно так же, как edit_file
; вы только что заменили жестко запрограммированную ссылку наself._latest_blob_sha_for_file
с аргументом функции.)
Затем каждая из ваших других функций просто вызывает _base
с соответствующим аргументом функции.В случае create_file
это явная функция, которая игнорирует свои аргументы и возвращает None
.
def create_file(self, file_blob, filename, commit_message, committer_info, branch):
return self._base(
file_blob,
filename,
commit_message,
committer_info,
branch,
lambda *args: None)
def edit_file(self, file_blob, filename, commit_message, committer_info, branch):
return self._base(
file_blob,
filename,
commit_message,
committer_info,
branch,
self._latest_blob_sha_for_file)
Вы можете еще больше уменьшить шаблон, определив функцию, которую возвращает соответствующий метод, закрывая аргумент функции.При таком подходе у вас еще нет доступа к self
, чтобы создать связанный метод для использования в edit_file
, поэтому вы должны явно передать self
в функцию обратного вызова.
class SomeClass:
def _make_method(fn):
def _base(self, file_blob, filename, commit_message, committer_info, branch):
file_blob_sha = fn(self, branch, filename)
json_file_data = self._file_data(file_blob, commit_message, committer_info, branch, file_blob_sha)
content_url = '{}/{}'.format(self._github_content_url, filename)
response = self._request(content_url, method='PUT', data=json_file_data)
self._handle_errors(response)
return _base
def _latest_blob_sha_for_file(self, branch, filename):
...
create_file = _make_method(lambda *args: None)
edit_file = _make_method(_latest_blob_sha_for_file)
del _make_method
Обратите внимание, что _make_method
не предназначен для самого метода;это просто вспомогательная функция, используемая для определения create_file
и edit_file
, поэтому мы удаляем ее из пространства имен класса до его создания.