LINUX.ORG.RU

Функции, видимые только локально в модуле

 , ,


0

1

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

★★★★★

Последнее исправление: I-Love-Microsoft (всего исправлений: 1)

на уровне модуля можно перечислить что может экспортироваться в этом модуле:

__all__ = [«public_function»]

xsandrk
()

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

Никак не сделать. Решение с __all__ это не про то. Оно влияет только на инструкцию from module import *, но так как раз и не советуют импортировать. А если ты просто сделаешь import module, то твой __all__ проигнорируется, и все «приватные» функции будут доступны.

Crocodoom ★★★★★
()
Ответ на: комментарий от Sahas

Где же это оно скрыто?

Что с подчеркиванием, что с __all__ — нерабочие варианты.

module.py

__all__ = []

def func(): print("OH SHI~")
def _func(): print("OH SHI~")
def __func(): print("OH SHI~")

>>> import module
>>> module.func()
OH SHI~
>>> module._func()
OH SHI~
>>> module.__func()
OH SHI~
Crocodoom ★★★★★
()
Ответ на: комментарий от Sahas

Я чего засомневался, в REPL с префиксами всё прекрасно импортируется.

vvn_black ★★★★★
()
Ответ на: комментарий от Sahas

Как скрыто? Выше говорится что это не сработает.

# в модуле
def test1():
	print("test1")
def _test2():
	print("test2")
import mymod
mymod.test1()
mymod._test2()
Вывод:
test1
test2
Спокойно себе так всё видит выводит...

I-Love-Microsoft ★★★★★
() автор топика
Ответ на: комментарий от Crocodoom

Еще говорят в классах нет приватных методов... Не знаю, хорошо ли это? Как без этого обходиться? Если надо, чтобы никто по ошибке не вызвал приватную функцию. Надеюсь в Python 4 это появится, не вижу как это бы ломало парадигму языка и библиотек. Если всё это можно имитировать локальными функциями, то почему бы не дожать идею.

I-Love-Microsoft ★★★★★
() автор топика
Последнее исправление: I-Love-Microsoft (всего исправлений: 2)
Ответ на: комментарий от I-Love-Microsoft

по ошибке не вызвал приватную функцию

В Питоне принято такие функции обозначать с подчёркиванием. А с вызывающей стороны, соответственно, не трогать такие функции. Но если очень хочется, то можно, т.к. язык такое не запрещает.

uuwaan ★★
()
Ответ на: комментарий от uuwaan

Понятно. Если есть такая договоренность, то хорошо.

I-Love-Microsoft ★★★★★
() автор топика
Ответ на: комментарий от I-Love-Microsoft

Конвенционально приватным считается всё, что начинается с (хотя бы) одного подчёркивания. Это и про методы в классе, и про имена в модуле, и вообще про всё, где встретишь. Большинство питонистов об этом знают, и стараются лишний раз такие имена не дёргать. На уровне языка обращаться к таким именам не запрещено. Всё, что ты хочешь семантически сделать служебным/приватным/внутренним - начинай с одного подчёркивания.

Дополнительно уже на уровне языка поддерживается так называемый name mangling: если атрибут/метод класса начинается с (хотя бы) двух подчёркиваний, то он не будет доступен как x.__spam. Он по-прежнему будет доступен, но уже под именем x._classname__spam. Аналогичного механизма для модулей нет, только для классов. И вот почему: это сделано вовсе не усложнения доступа к «приватным» полям класса, а для избежания конфликта имён в подклассах. В документации есть подробности. Так как в модулях такой проблемы нет, то и механизм этот не нужен.

Crocodoom ★★★★★
()
Ответ на: комментарий от Crocodoom

Так это известно, что в Питоне видно «все кишки», и их не спрятать :)

по автодополнению из REPL имена с подчёркиваниями не видны

Sahas ★★★★☆
()
Последнее исправление: Sahas (всего исправлений: 2)

Кстати, пытался вспомнить где я видел решение подобной задачи и вспомнил, в qtile используется вот такой вот импорт - модуль в отдельный каталог и волшебный __init__.py типа такого:

import traceback
import importlib


def safe_import(module_name, class_name):
    if type(class_name) is list:
        for name in class_name:
            safe_import(module_name, name)
        return
    package = __package__
    if not package:
        package = __name__
    try:
        module = importlib.import_module(module_name, package)
        globals()[class_name] = getattr(module, class_name)
    except ImportError as error:
        print(f'Can\'t Import class:' \
              f' {module_name}.{class_name} {error}')
        print(f'{traceback.format_exc()}')


# То что здесь явно не будет указано, не будет импортится из module.py
safe_import('.module', 'common_func')
vvn_black ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.