Классовое пространство имен без self
Я уже довольно давно пишу на питоне и никогда не задумывался над этим вопросом. Можно ли в питоне использовать поля и методы класса не указывая явно пространство имен как это делается в большинстве других языков? Вот, что я имею в виду
class Example:
def inner_method1(self):
print("abacaba")
def inner_method2(self):
inner_method1()
example = Example()
example.inner_method2()
Очевидно, работать так не будет, обращение к полю объекта должно быть таким:
self.inner_method1()
Когда кода много, все эти self'ы режут глаза. Можно ли обойтись без них?
Скорее всего я сам знаю ответ на этот вопрос, хотелось бы услышать ваше мнение, зачем так сделано
Ответы (1 шт):
Нельзя. Так заложено архитектурой языка.
Думаю, это можно описать следующей фразой из дзена питона (увидеть можно через import this):
Explicit is better than implicit.
Явное указание на текущий объект self и обращение через него, считаю, помогают ориентироваться в том к какой переменной/функции будет обращение. Ведь, если нет self, cls, то это глобальный объект
В пример ниже будет понятно, что будет вызвано:
def foo():
print('foo()')
class Example:
def foo(self):
print("self.foo()")
def inner_method2(self):
foo()
self.foo()
example = Example()
example.inner_method2()
Результат:
foo()
self.foo()
Как видно из результата, интерпретатор вызвал глобальную функцию, вместо внутренней.
Это отличается от логики в других языках, в которых без this поиск будет сначала внутри класса, например:
java (https://onlinegdb.com/B_N2BoqQy):
public class Main { static void foo() { System.out.println("Main.foo"); } static void bar() { System.out.println("Main.bar"); } static class InnerClass { InnerClass() { foo(); this.foo(); bar(); } void foo() { System.out.println("InnerClass.foo"); } } public static void main(String[] args) { new InnerClass(); } }Результат:
InnerClass.foo InnerClass.foo Main.barc# (https://onlinegdb.com/KE7kfoRv8):
using System; class HelloWorld { static void foo() { Console.WriteLine("foo"); } static void bar() { Console.WriteLine("bar"); } class InnerClass { public InnerClass() { foo(); this.foo(); bar(); } void foo() { Console.WriteLine("InnerClass.foo"); } } static void Main() { new InnerClass(); } }Результат:
InnerClass.foo InnerClass.foo Main.barc++ (https://onlinegdb.com/0fns14VmB):
#include <iostream> using namespace std; void foo() { cout << "foo" << endl; } void bar() { cout << "bar" << endl; } class HelloWorld { public: HelloWorld() { foo(); this->foo(); bar(); } void foo() { cout << "HelloWorld.foo" << endl; } }; int main() { HelloWorld obj; return 0; }Результат:
HelloWorld.foo HelloWorld.foo bar
PS.
Когда кода много, все эти self'ы режут глаза
Не знаю... у меня наличие self не вызывало проблем :) Наоборот, это дает понимание какие переменные/функции относятся к текущему объекту, а какие внешние
PPS.
Вместо self можно использовать другое, в данном случае это просто аргумент методов объекта, но так не рекомендуется делать.
В целях образования, пример:
class Example:
abc = 123
def foo(this):
print(this.abc)
def inner_method2(_):
_.foo()
example = Example()
example.inner_method2()