Другая реализация постоянной для Python
Я не мог найти хорошую реализацию констант, поэтому создал свой собственный! Давайте начнем!
Проверьте полный код в https://gist.github.com/ra101/aa27ff6e437f74ca56027a8c6b166882
Как это должно работать
class Links(ConstantClass): GITHUB = "https://github.com/ra101" WEB = "https://ra101.github.io/" LINKS = "dev.ra.101@protonmail.com" class Author(ConstantClass): NAME = "〈 RA 〉" WEB = Links.WEB LINKS = Links
Теперь Ссылки GitHub
должен вернуться https://github.com/ra101
и Связь. GitHub
или Ссылки New_contants
Оба должны возвращать ни один, не назначая и не создавая новое поле
1) Нам нужно издеваться над всеми сеттером в мета -классе, который будет использоваться основным классом.
class ConstantMeta(type): """ Meta Class for Constant, How Constant class would behave """ def __setattribute__(self, *args, **kwargs): # Override set method to make it immutable pass def __setattr__(self, *args, **kwargs): # Override set method to make it immutable pass def __setitem__(self, *args, **kwargs): # Override set method to make it immutable pass def __set__(self, *args, **kwargs): # Override set method to make it immutable pass
1.5) Давайте добавим внешний сеттер
def __force_set__(self, name, value): # A external set method to make sure we can update value in __new__ return super().__setattr__(name, value)
2) переопределить __new__
Чтобы сделать фактический класс
def __new__(cls, clsname, bases, clsdict): """ adding __keys__, __values__ fields and keys(), values() methods """ obj = super().__new__(cls, clsname, bases, clsdict) obj.__force_set__("__values__", []) obj.__force_set__("__keys__", []) for key, val in vars(obj).items(): if not key.startswith("__"): obj.__values__.append(val) obj.__keys__.append(key) obj.__force_set__("keys", lambda: obj.__keys__) obj.__force_set__("values", lambda: obj.__values__) return obj
2.5) Добавить ниже методы полировки класса
def __getitem__(cls, key): # adding __getitem__ to make objects "subscriptable" return getattr(cls, key) def __iter__(cls): # In case of for loops return zip(cls.__keys__, cls.__values__)
3) Наконец -то давайте создадим класс!
class ConstantClass(metaclass=ConstantMeta): """ Now this class can be inherited whenever required to make constants """ pass
Окончательно! Мы сделали! Мы создали почти неизменный класс, который можно использовать в качестве константы
Примеры
Вход:
class Links(ConstantClass): GITHUB = "https://github.com/ra101" WEB = "https://ra101.github.io/" LINKS = "dev.ra.101@protonmail.com" class Author(ConstantClass): NAME = "〈 RA 〉" WEB = Links.WEB LINKS = Links Links.WEB = 'any_new_value' print(f"\nLinks.WEB: {Links.WEB}") print(f"\nAuthor.values(): {Author.values()}") print(f"\ndict(Author): {dict(Author)}") print("\nfor key in Author.LINKS.keys()") for key in Author.LINKS.keys(): print(f'getattr(Author.LINKS, "{key}"): {getattr(Author.LINKS, key)}')
Выход:
Links.WEB: https://ra101.github.io/ Author.values(): ['〈 RA 〉', 'https://ra101.github.io/', <__main__.ConstantClass object at 0x00000293A94768E0>] dict(Author): {'NAME': '〈 RA 〉', 'WEB': 'https://ra101.github.io/', 'LINKS': <__main__.ConstantClass object at 0x00000293A94768E0>} for key in Author.LINKS.keys() getattr(Author.LINKS, "GITHUB"): https://github.com/ra101 getattr(Author.LINKS, "WEB"): https://ra101.github.io/ getattr(Author.LINKS, "EMAIL"): dev.ra.101@protonmail.com
Проверьте полный код в https://gist.github.com/ra101/aa27ff6e437f74ca56027a8c6b166882
Оригинал: “https://dev.to/ra101/python-reimaging-constants-1ghh”