Почему идентификатор метода экземпляра отличается от идентификатора ссылки на метод экземпляра? [Дубликат]

Альтернативы mod_rewrite

Многие базовые схемы виртуальных URL-адресов могут быть достигнуты без использования RewriteRules. Apache позволяет запускать скрипты PHP без расширения .php и с виртуальным аргументом PATH_INFO.

  1. Используйте PATH_INFO , Luke

    В настоящее время AcceptPathInfo On часто включается по умолчанию. В основном это позволяет .php и другим URL-адресам ресурсов переносить виртуальный аргумент:
    http://example.com/script.php/virtual/path
    
    Теперь этот /virtual/path отображается в PHP как $_SERVER["PATH_INFO"] , где вы можете обрабатывать любые дополнительные аргументы, как вам нравится. Это не так удобно, как разделить сегменты входного пути Apache на $1, $2, $3 и передать их как различные переменные $_GET в PHP.

  2. Включить MultiViews , чтобы скрыть расширение .php

    . Самый простой вариант - также отключить .php «Расширения файлов» в URL-адресах разрешены:
    Options +MultiViews
    
    Это означает, что Apache выбирает article.php для HTTP-запросов на /article из-за соответствующего базового имени. И это хорошо работает вместе с вышеупомянутой функцией PATH_INFO. Таким образом, вы можете просто использовать URL-адреса, такие как http://example.com/article/virtual/title. Это имеет смысл, если у вас есть традиционное веб-приложение с несколькими точками / сценариями PHP-скриптов. Обратите внимание, что MultiViews имеет другую / более широкую цель. Это повлечет за собой незначительное исполнение, потому что Apache всегда ищет другие файлы с соответствующими базовыми именами. Это фактически означает Content-Negotiation , поэтому браузеры получают лучшую альтернативу доступным ресурсам (например, article.en.php, article.fr.php, article.jp.mp4).
  3. SetType или SetHandler для сценариев без расширения .php

    . Более ориентированный подход, чтобы избежать переноса суффиксов .php в URL-адресах, - это настройка обработчика PHP для других файловых схем. Самый простой вариант - переопределить тип MIME / обработчика по умолчанию через .htaccess:
    DefaultType application/x-httpd-php
    
    Таким образом, вы можете просто переименовать свой скрипт article.php только в article (без расширения), но все же обработать его как PHP-скрипт. Теперь это может иметь некоторые последствия для безопасности и производительности, поскольку теперь все файлы без расширения будут переданы через PHP. Поэтому вы можете альтернативно установить это поведение только для отдельных файлов:
    
      SetHandler application/x-httpd-php
      # or SetType 
    
    
    Это несколько зависит от настройки вашего сервера и используемого PHP SAPI. Общие альтернативы включают ForceType application/x-httpd-php или AddHandler php5-script. Снова обратите внимание, что такие настройки распространяются от одного .htaccess до подпапок. Вы всегда должны отключать выполнение сценария (SetHandler None и Options -Exec или php_flag engine off и т. Д.) Для статических ресурсов и загрузки / каталогов и т. Д.
  4. Другие схемы перезаписи Apache

    Среди его много вариантов, Apache предоставляет функции mod_alias, которые иногда работают так же хорошо, как и mod_rewrite s RewriteRules. Обратите внимание, что большинство из них должны быть настроены в разделе , но не в файлах конфигурации .htaccess для каждого каталога. ScriptAliasMatch в первую очередь предназначен для скриптов CGI, но также должен работать для PHP. Он позволяет регулярные выражения так же, как и любые RewriteRule. На самом деле это, пожалуй, самый надежный вариант для конфигурирования переднего контроллера. И простой Alias помогает с несколькими простыми схемами перезаписи. Даже простая директива ErrorDocument может использоваться, чтобы позволить скрипту PHP обрабатывать виртуальные пути. Обратите внимание, что это обходное решение kludgy, однако, запрещает все, кроме запросов GET, и наводняет error.log по определению. См. http://httpd.apache.org/docs/2.2/urlmapping.html для получения дополнительных советов.

13
задан Stefan Pochmann 14 May 2015 в 07:21
поделиться

2 ответа

Объекты метода создаются каждый раз, когда вы обращаетесь к ним . Функции действуют как дескрипторы , возвращая объект метода, когда вызывается метод .__get__:

>>> What.__dict__['meth']
<function meth at 0x10a6f9c80>
>>> What.__dict__['meth'].__get__(None, What)
<unbound method What.meth>
>>> What.__dict__['meth'].__get__(What(), What)
<bound method What.meth of <__main__.What object at 0x10a6f7b10>>

Вместо этого используйте проверку равенства ==.

Два метода равны, если их атрибуты .im_self и .im_func идентичны. Если вам нужно проверить, что методы представляют одну и ту же основную функцию , проверьте их атрибуты im_func:

>>> What.meth == What.meth     # unbound methods (or functions in Python 3)
True
>>> What().meth == What.meth   # unbound method and bound method
False
>>> What().meth == What().meth # bound methods with *different* instances
False
>>> What().meth.im_func == What().meth.im_func  # functions
True
21
ответ дан Martijn Pieters 21 August 2018 в 16:31
поделиться
  • 1
    Если я использую ==, я получу поведение идентичности, которое я искал? – Claudiu 12 April 2013 в 18:56
  • 2
    Я думаю, что метод равенства проверяет тождество для .im_self, а не равенство. проверить – Claudiu 12 April 2013 в 19:06
  • 3
    @Claudiu: да, извините, он проверяет, идентичен ли im_self. – Martijn Pieters♦ 12 April 2013 в 19:08
  • 4
    @Claudiu Claudiu, Martijn: вы имеете в виду, что в комментариях этот метод проверяет идентичность для im_self AND im_func , не так ли? Это то, что было исправлено в редактировании, не так ли? – eyquem 20 January 2014 в 05:00
  • 5
    Можно ли пересмотреть этот ответ? Описание того, как im_self рассматривается в сравнении сравнений метода, в настоящее время неверно. – user2357112 22 August 2017 в 20:34

Martijn прав, что новые методы являются объектами, сгенерированными .__get__, поэтому их указатели адресов не приравниваются к оценке is. Обратите внимание, что использование == будет оцениваться как указано в Python 2.7.

Python2.7
class Test(object):
    def tmethod(self):
        pass

>>> Test.meth is Test.meth
False
>>> Test.meth == Test.meth
True

>>> t = Test()
>>> t.meth is t.meth
False
>>> t.meth == t.meth
True

Обратите внимание, однако, что методы, ссылающиеся на экземпляр, не приравниваются к тем, на которые ссылается класс, из-за саморекламы, проведенной вместе с методом из экземпляра.

>>> t = Test()
>>> t.meth is Test.meth
False
>>> t.meth == Test.meth
False

В Python 3.3 оператор is для методов более часто ведет себя так же, как ==, поэтому вместо этого вы получите ожидаемое поведение в этом примере. Это связано с исчезновением __cmp__ и представлением объекта более чистого метода в Python 3; методы теперь имеют __eq__, а ссылки не являются объектами «на лету», поэтому поведение следует за тем, как можно было ожидать без ожиданий Python 2.

Python3.3
>>> Test.meth is Test.meth
True
>>> Test.meth == Test.meth
True
>>> Test.meth.__eq__(Test.meth)
True
1
ответ дан Pyrce 21 August 2018 в 16:31
поделиться
  • 1
    Ваш анализ отключен. Изменения, которые вы наблюдали в Python 3, не связаны с is; они связаны с исчезновением объектов unbound method в Python 3. Теперь Test.meth - это только определенный объект функции, который вы определили, вместо объекта unbound method, созданного «на лету». – user2357112 29 January 2017 в 00:32
  • 2
    Ах, да, я добавил некоторые уточняющие детали, чтобы включить проблему с несвязанным объектом. – Pyrce 31 January 2017 в 20:10
Другие вопросы по тегам:

Похожие вопросы: