Меня тут один умник попросил прокомментировать некоторые куски моего кода, а я подумал, что это может оказаться интересным для многих. Да и критику я люблю. Только нормальную, а не: "Это, скуцо, всё фуфло! Медведа на вас нет!.."
Итак, как я уже говорил, пишу я сейчас, главным образом на PyQt4. В Qt, пришедшем из C++, мы привыкли к управлению свойствами класса в стиле:
class c(QWidget):
...
def variable(self):
return ...
def setVariable(self, Value):
...Это довольно удобно, особенно когда нужно переопределить метод. Однако питон предоставляет более красивую возможность:class c(QWidget):
def variable(self):
return ...
def setVariable(self, Value):
...
Variable = property(variable, setVariable, lambda self: None)Теперь мы можем использовать Variable гораздо удобнее:o = c()
o.Variable = True
Var = o.VariableТретий параметр property нужен для невозможности удалить Variable путём "del o.Variable". Его можно опустить.Если нам нужно передать в setVariable несколько аргументов, то замечательно работает такая запись:
class c(QWidget):
def variable(self):
return ...
def setVariable(self, arg1, arg2, arg3):
...
Variable = property(variable,
lambda self, args: self.setVariable(*args),
lambda self: None)
o = c()
o.Variable = arg1, arg2, arg3Думаю, что тут всё понятно.Довольно интересная проблема состоит в том, что если переопределить методы variable и setVariable, то вызываться они не будут, потому что property сохраняет ссылки на методы того класса в котором они определены. На помощь нам придёт lambda.
class c(QWidget):
def variable(self):
return ...
def setVariable(self, Value):
...
Variable = property(
lambda self: self.variable(),
lambda self, Value: self.setVariable(Value),
lambda self: None)Ламбда функции это вообще очень сильный механизм. Когда я в него въехал, то многие вещи стали решаться гораздо легче, чем раньше.Вот небольшой пример из моего проекта:
class ModulesStack(QDialog):
def __init__(self, Parent):
... ## Определение, заполнение виджета...
self.Modules = [mod1, mod2, mod3] ## У модуля (modX) есть параметр Visible,
##определённый, кстати, с помощью property и возвращающий True или False.
def visibleModules(self): return filter(lambda Mod: Mod.Visible, self.Modules)
VisibleModules = property(
lambda self: self.visibleModules(),
lambda self, Modules: self.Modules = Modules,
lambda self: None)Или, вообще страшный вариант:class User(QObject):
'''Информация о пользователи + кэш'''
def __init__(self, UserId):
QObject.__init__(self)
self.UserId = UserId
self.LoadTimestamp = None
self.load()
def clear(self):
for par in [
"Login", "CreateTimestamp", "UpdateTimestamp", "DeleteTimestamp", "Inactive",
"Surname", "Name", "Patronymic", "Sex", "Birthday", "Description",
"CountryId", "RegionId", "SityId", "Address",
"EMail", "Jabber", "ICQ", "Http", "Ftp",
"PhoneHome", "PhoneWork", "PhoneMobile"
]:
exec """self.%s = None""" % par
self.ExpireDate = QDate.fromString("2099-12-31", "yyyy-MM-dd")
def load(self):
'''Эта функция фактически состоит из запроса серверу (опущен) и множества приравниваний.'''
...
self.Login = rq.Dict["System"].get("Login", None)
self.CreateTimestamp = rq.Dict["System"].get("CreateTimestamp", None)
self.UpdateTimestamp = rq.Dict["System"].get("UpdateTimestamp", None)
...
def profLoad(self):
'''Вызывается при каждом запросе параметра, проверяет, не пора ли обновить '''
'''информацию и, в случае надобности, вызывает load. '''
'''Собственно ради неё все эти замутнения и сделаны.'''
...
for par in [
"UserId", "Login", "CreateTimestamp", "DeleteTimestamp",
"UpdateTimestamp", "Inactive", "ExpireDate",
"Surname", "Name", "Patronymic", "Nick", "Sex", "Birthday", "Description",
"CountryId", "RegionId", "SityId", "Address",
"EMail", "Jabber", "ICQ", "Http", "Ftp",
"PhoneHome", "PhoneWork", "PhoneMobile"
]:
exec """_%s = None""" % par
exec \
"""def %s(self):
self.profLoad()
return self._%s""" % (par[0].lower() + par[1:], par)
exec \
"""def set%s(self, Value):
self._%s = Value
self._emitSetSignal("%s", Value)""" % ((par,) * 3)
exec \
"""%s = property(%s, set%s, lambda self: self.set%s(None))""" % (par, par[0].lower() + par[1:], par, par)
del parP.S. Вы уж скажите, если кому интересно, а то, может, я зря распинаюсь и засоряю форум...P.P.S. Мне тут намекнули на то, что в такой нотации классы становятся похожи на VCL. Блин, действительно. А я и не заметил. Просто последняя дельфя, которую я видел, была четвёртой версии...
Last edited April 3, 2008, 5:42 a.m.
-- Я -- часть той силы, что вечно хочет зла
и вечно совершает благо.