Дескриптор — что это в программировании
Дескриптор (видимо от англ «describe/description» = «описывать/описание») — это некий набор данных (часто это переменная/объект особого типа), описывающий какую-либо сущность, но при этом им не являющийся.
(что вроде паспорта какой-либо страны, относительно реального человека).
Дескриптор файла
Дескриптор файла — часто это переменная того типа данных, который возвращает в вашем ЯП, например, функция открытия файла, в этом случае дескриптор обычно, помимо прочего, содержит сведения об адресе расположения файла (например, пути к нему в рамках файловой системы).
Что такое дескриптор.
Обьясните пожалуйста, что такое дескриптор, касаясь функции winmain. Вот я читаю справку из msdn от vc++ на счет синтаксиса этой функции и там написано, что первые два параметра это дескрипторы, что это значит?
#1
13:38, 11 дек 2006
HINSTANCE. Уникальный идентификатор (число), ассоциированный с экземпляром твоего приложения, выполняемого в Windows.
Гы, помню классе в шестом я курил книжку по программированию под винду. Мне потребовалось 5 недель, чтобы осознать, что такое дескриптор окна =)
#2
13:45, 11 дек 2006
Если не трудно, вот само слово дескриптор что значит? Пожалуйста.:)
#3
13:47, 11 дек 2006
>Если не трудно, вот само слово дескриптор что значит? Пожалуйста.:)
Буквально — описатель. Идентификатор, как уже сказал ZET
#4
14:10, 11 дек 2006
Yaricoss
Твой гражданский паспорт, это твой дескриптор. ФСБ, зная серию и номер твоего паспорта, могут получить о тебе информацию и по ней найти тебя. Этот дескриптор уникальный, то есть ФСБ однозначно на тебя выйдут, а не на кого-то другого.
Аналогично, дескриптор может иметь приложение. Используется вместо, например, указателя, поскольку не все языки программирования могут использовать указатели. Также и окно определяется дескриптором. Например у тебя в программе несколько окон, нужно одно открыть, другое закрыть. При помощи дескрипторов окна (HWND) ты определяешь — с каким конкретно окном будешь работать.
#5
14:46, 11 дек 2006
Спасибо. Понятней определения наверно нигде не найдешь! А вот второй(если не лень то третий и четвертый) параметр WinMain можете разъяснить. Буду очень благодарен.
#6
14:52, 11 дек 2006
Напишу несколько статей под названием «Чайник — Чайнику. DirectX 9», чтоб чайники, типа меня не задавали таких вопросов.
#7
16:57, 11 дек 2006
Yaricoss
>Спасибо. Понятней определения наверно нигде не найдешь! А вот второй(если не
>лень то третий и четвертый) параметр WinMain можете разъяснить. Буду очень благодарен.
>Напишу несколько статей под названием «Чайник — Чайнику. DirectX 9», чтоб
>чайники, типа меня не задавали таких вопросов.
Какое отношение WinMain() имеет к DirectX 9?
По поводу аргументов WinMain надо идти сюда: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/… s/winmain.asp
#8
20:32, 11 дек 2006
Ну, незнаю(пока) какое это отношение имеет к Directx, вам виднее. Во всяком случае, winmain я встречал во многих примерах из dx sdk. Ссылка конечно хорошая, но это все и даже большее у меня есть(из msdn от vc++). Хотелось бы увидеть чтонибудь, написанное простым всем понятным языком.
#9
20:58, 11 дек 2006
Yaricoss
Если тебе МСДН не по зубам (хе-хе. ), найди где-нить книжку «Чарльз Калверт. Освой самостоятельно программирование в Windows за 21 день». У меня есть довольно старое издание, времён Windows 95. не знаю, может её переиздавали с учётом развития отрасли. Однако, несмотря на давность, весь материал актуален даже сейчас. Книга просто офигенно на пальцах рассказывает о программировании под винду с нуля. Чисто WinAPI на Си, без дотнетов, даже без MFC. Первые страниц 200 разжёвывают базу, но страницы с 600ой книга становится довольно непростой в освоении для начинающего, и в целом она покрывает очень большой объём информации. Рассматриваются вопросы организации windows-приложения, создание окон, common controls, GDI, ресурсы windows, диалоги, немного извращённых техник типа сабклассинга, механизмы управления памятью, механизмы многозадачности (в том числе методы синхронизации), многооконные приложения.
Если хочется хардкорщины, можно искать в инете E-Book «Джеффри Рихтер. Что-то там типа кодинг под винду и бла бла». На английском есть онлайн нахаляву, во многих местах. Эта книга подразумевает, что вы уже полностью понимаете все основные вещи.
ООП. Дескрипторы
В этой лекции мы рассмотрим такой важный механизм как дескрипторы, а также разберемся с тем как же устроены методы класса.
Свойства
Перед тем как говорить о дескрипторах давайте еще раз поговорим о свойствах (property). Рассмотрим следующий пример: пусть у нас есть класс «Профиль пользователя», который включает следующие поля: имя, фамилия и дата рождения.
import typing as tp class UserProfile: def __init__(self, user: "User", first_name: str = "", sur_name: str = "", bdate: tp.Optional[datetime.date] = None) -> None: self._user = user self.first_name = first_name self.sur_name = sur_name self.bdate = bdate self._age = None self._age_last_recalculated = None self._recalculate_age() def _recalculate_age(self) -> None: if self.bdate is None: return today = datetime.date.today() age = today.year - self.bdate.year if today datetime.date(today.year, self.bdate.month, self.bdate.day): age -= 1 self._age = age self._age_last_recalculated = today def age(self) -> tp.Optional[int]: if self._age is None: return None if datetime.date.today() > self._age_last_recalculated: self._recalculate_age() return self._age class User: def __init__(self, username: str, email: str, password: str) -> None: # . self.profile = UserProfile(self) # . >>> guido = User("guido", "guido@python.org", "python") >>> guido.profile.age() >>> guido.profile.bdate = datetime.date(1956, 1, 31) >>> guido.profile.age() 65
Из примера видно, что, во-первых, возраст пользователя вычисляется при каждом обращении, во-вторых, мы только получаем значение и никогда его не изменяем. Было бы логично, чтобы клиентский код работал с возрастом как с обычным атрибутом (свойством) доступным только для чтения и python предоставляет нам для этого механизм свойств (propertes):
class UserProfile: # . @property def age(self) -> Optional[int]: if self._age is None: return None if datetime.date.today() > self._age_last_recalculated: self._recalculate_age() return self._age >>> guido = User("guido", "guido@python.org", "python") >>> guido.profile.age >>> guido.profile.bdate = datetime.date(1956, 1, 31) >>> guido.profile.age 65 >>> guido.profile.age = 66 # . AttributeError: can't set attribute
Таким образом, свойства дают нам возможность создавать, аналогично другим языкам программирования (например, Java), сеттеры и геттеры, а также вычисляемые свойства (computed properties):
class UserProfile: # . @property def fullname(self) -> str: return f" ".title() @fullname.setter def fullname(self, value: str) -> None: name, surname = value.split(" ", maxsplit=1) self.first_name = name self.sur_name = surname @fullname.deleter def fullname(self) -> None: self.first_name = '' self.sur_name = '' >>> guido.profile.fullname = "Guido Van Rossum" >>> guido.profile.first_name 'Guido' >>> guido.profile.sur_name 'Van Rossum' >>> del guido.profile.fullname >>> guido.profile.first_name '' >>> guido.profile.sur_name ''
Чтобы понять как работают свойства необходимо разобраться с дескрипторами.
Дескрипторы
В документации дано следующее определение дескрипторов:
Дескриптор это любой объект, у которого определены методы __get__() , __set__() или __delete__() . Если дескриптором является атрибут класса, то для него определено специальное поведение при разшенении имени атрибута.
descr.__get__(self, obj, owner=None) -> value descr.__set__(self, obj, value) -> None descr.__delete__(self, obj) -> None
Дескрипторы, которые реализуют только __get__ называются дескрипторами не данных (non-data descriptors), а дескрипторы, которые реализуют __set__ и/или __delete__ называются дескрипторами данных (data descriptors). Рассмотрим следующий пример:
class D: def __get__(self, obj, owner=None): print(f"__get__ был вызван с аргументами obj= и owner=") def __set__(self, obj, value): print(f"__set__ был вызван с аргументами obj= и value=") class Klass: d1 = D() def __init__(self): self.d2 = D() >>> obj = Klass() >>> obj.d1 # == type(obj).__dict__['d1'].__get__(obj, type(obj)) __get__ был вызван с аргументами obj=__main__.Klass object at 0x1037d4c10> и owner=class '__main__.Klass'> >>> obj.d2 # == obj.__dict__['d2'] __main__.D at 0x1052521c0> >>> Klass.d1 # == Klass.__dict__['d1'].__get__(None, Klass) __get__ был вызван с аргументами obj=None и owner=class '__main__.Klass'> >>> obj.d1 = None # == type(obj).__dict__['d1'].__set__(obj, None) __set__ был вызван с аргументами obj=__main__.Klass object at 0x1037d4c10> и value=None >>> Klass.d1 = None # Klass.__dict__['d1'] = None
Из примера видно, что при обращении к d1 автоматически был вызван метод __get__ определенный на дескрипторе:
Поведением по умолчанию при доступе к атрибуту является обращение к словарю экземпляра, например, при обращении к a.x поиск начинается с a.__dict__[‘x’] , затем type(a).__dict__[‘x’] и так далее в порядке разрешения методов (mro). Когда же атрибут (класса/метакласса) является дескриптором, то Python изменяет путь поиска, сначала вызывая методы определенные у дескриптора.
Поэтому теперь должно быть понятно, почему при обращении к d2 мы получили просто экземпляр класса. Порядка разрешения имен атрибутов и методов мы коснемся в следующих лекциях.
В Python дескрипторы используются достаточно часто, в том числе и в самом языке, например, функции это дескрипторы:
PyTypeObject PyFunction_Type = PyVarObject_HEAD_INIT(&PyType_Type, 0) "function", sizeof(PyFunctionObject), 0, // . function_call, /* tp_call */ // . func_descr_get, /* tp_descr_get */ 0, /* tp_descr_set */ // . >;
Это позволяет автоматически передавать экземпляр класса в качестве первого аргумента ( self ), давайте посмотрим на вызов func_descr_get :
/* Bind a function to an object */ static PyObject * func_descr_get(PyObject *func, PyObject *obj, PyObject *type) if (obj == Py_None || obj == NULL) Py_INCREF(func); return func; > return PyMethod_New(func, obj); >
Если obj не был передан, то мы имеем дело с обычной функцией, в противном случае это метод и мы «биндим» объект в качестве первого аргумента. На python реализацию функций можно было бы записать так:
class Function: def __call__(self, *args, **kwargs): # тело функции def __get__(self, instance, owner): if instance is None: return self else: return functools.partial(self, instance)
А вот примеры реализаций декораторов @staticmethod и @classmethod:
import functools class Classmethod: def __init__(self, func): self.func = func def __get__(self, instance, owner): return functools.partial(self.func, owner) class Staticmethod: def __init__(self, func): self.func = func def __get__(self, instance, owner): return self.func
И наконец реализация @property:
class Property: def __init__(self, fget=None, fset=None, fdel=None): self.fget = fget self.fset = fset self.fdel = fdel def __get__(self, instance, owner): if instance is None: return self elif self.fget is None: raise AttributeError("Unreadable attribute") else: return self.fget(instance) def __set__(self, instance, value): if self.fset is None: raise AttributeError("Cant't set attribute") else: self.fset(instance, value) def __delete__(self, instance): if self.fdel is None: raise AttributeError("Can't delete attribute") else: self.fdel(instance) def getter(self, fget): return type(self)(fget, self.fset, self.fdel) def setter(self, fset): return type(self)(self.fget, fset, self.fdel) def deleter(self, fdel): return type(self)(self.fget, self.fset, fdel)
Пример простой ORM можно найти в репозитории с лекциями.
Что такое дескриптор в программировании
Евдокимов А.А., Майстренко Н.В., Майстренко А.В.
2.3.3.1. Дескрипторы
Ссылки пользовательского режима на объекты режима ядра не могут использовать указатели, поскольку их трудно проверить. Для ссылки на объекты режима ядра Windows использует описатели(handles, часто также называемые дескрипторами).
Описатели — это неявные значения, которые конвертируются диспетчером объектов в ссылки на представляющие объект специфические структуры данных режима ядра.
На рис. 2.8 показана структура данных таблицы дескрипторов, используемой для трансляции описателей в указатели на объекты.
На рис. 2.9 показана таблица описателей с двумя дополнительными уровнями косвенного обращения. Для выполняющегося в режиме ядра кода иногда бывает удобно иметь возможность использовать описатели (а не указатели со ссылками).
Они называются описателями ядра и специальным образом кодируются, чтобы их можно было отличить от описателей пользовательского режима.
Точно так же как и большая часть виртуального адресного пространства ядра, системная таблица описателей совместно используется всеми компонентами ядра вне зависимости от того, какой процесс пользовательского режима является текущим.