V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  keakon  ›  全部回复第 11 页 / 共 55 页
回复总数  1087
1 ... 7  8  9  10  11  12  13  14  15  16 ... 55  
2017-09-02 00:55:32 +08:00
回复了 f12998765 创建的主题 Python 为什么描述符不能定义为实例属性
先想想对象和类调用时,为什么传给 __get__ 的参数要不一样。再想想类也是对象,如果要满足你的设定,__get__ 的参数就得一样了。
2017-08-31 09:50:24 +08:00
回复了 f12998765 创建的主题 Python 为什么描述符不能定义为实例属性
https://docs.python.org/3/howto/descriptor.html#invoking-descriptors

For objects, the machinery is in object.__getattribute__() which transforms b.x into type(b).__dict__['x'].__get__(b, type(b)). The implementation works through a precedence chain that gives data descriptors priority over instance variables, instance variables priority over non-data descriptors, and assigns lowest priority to __getattr__() if provided. The full C implementation can be found in PyObject_GenericGetAttr() in Objects/object.c.

For classes, the machinery is in type.__getattribute__() which transforms B.x into B.__dict__['x'].__get__(None, B).
2017-08-27 16:24:06 +08:00
回复了 saximi 创建的主题 Python 请教一个关于元类的问题
1. callable 的检查是查看它的类型是否有 tp_call: x->ob_type->tp_call != NULL。
而 type 在它的 C 实现里,将 tp_call 设为了之前我提到的 type_call 函数。
而且 type 的类型也是 type,所以 type 的类型实现了 tp_call,因此它是 callable 的。

3. 生成的那个 Meta1 实例就是 Meta2。接着 type.__call__ 调用了 Meta1 定义里的 __new__ 和 __init__ 对 Meta2 进行初始化。

4. 定义 Spam 类时,不会再调用 Meta1(),因为你传入的是 metaclass=Meta2,而不是 metaclass=Meta1(...)。
不是因为 Meta2 已经生成了,所以不需要重新生成,而是你传入的就是 Meta2 这个对象,而不是再传入一个新的 Meta1 类的实例。

5. 同上。
2017-08-27 11:37:20 +08:00
回复了 saximi 创建的主题 Python 请教一个关于元类的问题
类在声明时定义了 __call__ 方法后,它的实例才是 callable 的。
元类都继承自 type,type 定义了 __call__ 方法。类是元类的实例,所以类都是 callable 的。元类也是 type 的实例,也是类,所以也是 callable。
2017-08-27 11:29:44 +08:00
回复了 saximi 创建的主题 Python 请教一个关于元类的问题
2017-08-27 11:11:06 +08:00
回复了 saximi 创建的主题 Python 请教一个关于元类的问题
其实不需要理解,只是 Python 是这样实现的。
你去看它的 C 实现,调用时会先用 __new__ 方法去生成一个对象,如果这个对象是目标类的实例,就再调用 __init__ 方法,否则直接返回。其他面向对象的语言也需要某种机制去调用父类的构造函数,至于是 runtime 或编译器自动做的,还是手写,就看语言的设计者了。
实际使用中你根本不会有 override type.__call__ 的需求,元类的 __new__ 已经能干任何事了,它连签名都和 __call__ 一样,只是不会自动调用 __init__ 而已。
另外,type.__call__() 等效于 type()。
2017-08-27 01:19:39 +08:00
回复了 saximi 创建的主题 Python 请教一个关于元类的问题
1. Meta2 是 callable,不是因为它定义了 __call__ 方法,而是它的父类( Meta1 )定义了 __call__ 方法。
另外,__new__ 和 __init__ 是由 type.__call__() 负责调用的。
2. 假设 obj 是 Cls 类的实例,obj() 等效于 obj.__call__(),等效于 Cls.__call__(obj)。
或者更通用点,obj.f(1) 等效于 Cls.f(obj, 1)。
这个语法实现在 Python 文档里有描述(搜「 Instance methods 」): https://docs.python.org/3/reference/datamodel.html
实现原理是用 descriptor,详细实现可以参考: https://www.keakon.net/2009/12/08/%E7%94%A8Descriptor%E5%AE%9E%E7%8E%B0%E5%8F%A6%E4%B8%80%E7%A7%8D%E9%A3%8E%E6%A0%BC%E7%9A%84Decorator
2017-08-26 14:21:51 +08:00
回复了 saximi 创建的主题 Python 请教一个关于元类的问题
你先理解元类是类的类,元类的实例是类。

所以在定义 Meta2 时( class Meta2(type, metaclass=Meta1)),实际上是生成了一个 Meta1 的实例,就需要调用 Meta1 的 __new__ 和 __init__。
而在定义 Spam 时( class Spam(Eggs, metaclass=Meta2)),需要生成一个 Meta2 的实例作为 Spam 类,也就是执行
Meta2()。Meta2 是个 callable 的对象,调用它实际上是调用 Meta2.__call__(...),这个调用又会被转变成 Meta1.__call__(Meta2, ...)。而你在这个方法里调用了 type.__call__(),这个方法会负责去调用 Meta2.__new__() 和 Meta2.__init__()。

最后,Meta1.__call__() 是负责创建 Meta2 的对象的,Meta2.__call__() 是负责创建 Spam 的对象的。在执行 Spam() 时,Meta2 已经在定义 Spam 类时就被创建过了,创建 Spam 的对象时不需要再调用 Meta1.__call__() 创建新的 Meta2,而是直接使用已有的 Meta2 创建 Spam 的对象。
2017-08-17 10:55:37 +08:00
回复了 xinhangliu 创建的主题 Python 问几个关于 __getattr__() 的问题,求解答
1. 代码不可复用。
2. 常见,但由于效率较低,所以不到万不得已一般也不用。Ruby 的话倒是经常这么干。除此以外还可以用 descriptor 机制(__get__),代码量会多一些,但是 IDE 可以识别这些属性,避免出现警告。
3. url 是传给 Answer(self, url) 的,这是你要暴露出去的参数,干掉就没法初始化了。你实在不想给 getter 起名,可以 return lambda url: getattr(module, item.capitalize())(url, session=self._session)。
2017-08-15 10:18:14 +08:00
回复了 autoxbc 创建的主题 程序员 V2EX 的 csrfToken 设计缺陷及修正
印象中 V2EX 应该是用 Tornado 实现的,默认的 csrfToken 是保存在 cookie 中的,服务端并不保存,而是检查 POST 的数据是否和 cookie 中一致。至于每个页面都更新 csrfToken,则不是 Tornado 干的。
2017-08-11 19:31:36 +08:00
回复了 kran 创建的主题 Vim 如何让 vim 认为 PHP 变量中的$是变量的一部分?
autocmd FileType php setlocal iskeyword+=$
2017-08-10 18:50:58 +08:00
回复了 wencan 创建的主题 Python 请教 lxml 分析 html 的问题
因为这是个错误的 html,font 是 inline 元素,center 是 block 元素,lxml 在构造时会把 center 移到 font 外部。
2017-08-07 11:13:25 +08:00
回复了 SlipStupig 创建的主题 Python Python websocket-client 如何保持长连接呢?
create_connection 放循环外去啊…
2017-07-25 10:14:13 +08:00
回复了 Livid 创建的主题 NGINX 关于 NGINX 的 upstream 配置的 fail_timeout=0 参数的意义
看了下源码,nginx 发现连接超时、读取超时、status code >= 300 就会尝试下一个 upstream,如果它成功就换它响应,如果它失败就自己返回失败。
所以对于动态服务器,确实应该禁用。
2017-07-19 10:41:03 +08:00
回复了 SlipStupig 创建的主题 Python Python 内存泄露怎么能快速诊断?
其实大多数时候没啥好办法,因为一般你写不出能内存泄露的代码,这些问题基本都是第三方库导致的。粗暴的话就每隔一段时间或处理一定请求后自动重启进程,非要找找可以参考这篇 http://www.jianshu.com/p/2d06a1a01cc3
2017-07-05 18:15:14 +08:00
回复了 jsonzz 创建的主题 Python 执行类方法前,如何获取方法入参并修改
你要做的就是修改 swimming 的实现,使用 override 不是最简单的么,看不出哪里复杂:
def swimming(self, action):
return C.swimming(self, self.add_punctuation(action)) # 或者 return super(C1, self).swimming(self.add_punctuation(action))

如果你有一堆方法需要修改参数,先写一个 decorator,用处是计算并传递新参数;然后再写个 metaclass,对满足要求的方法都应用上这个 decorator。
这个问题看着挺绕的,但是道理却很简单。

假如要用 native coroutine 来实现「 pause execution and force something to be sent down to the event loop 」,那么你写的代码大概如下:
async def native_coroutine(): # ...
async def f(): await native_coroutine()

再来看 native_coroutine 的函数体,你有如下选择:
1. await 一个 awaitable 对象:这会导致你需要再定义一个 native coroutine,递归回到前面的选择。
2. return 一个值:这会导致代码变成同步的,f 函数会立刻接收到 StopIteration 异常。
3. raise 一个异常:这会导致代码变成同步的,f 函数会立刻接收到异常。
4. yield 一个值:在 Python 3.5 或之前是语法错误;在 3.6 或之后它变成了 asynchronous generator (见 PEP 525 ),也不能用在 await 表达式里(它不是 awaitable,没有定义 __await__ 方法,会抛出 TypeError: object async_generator can't be used in 'await' expression )。

对于选择 1,你当然也可以自定义一个 awaitable:
class Awaitable(object):
----def __init__(self, count):
--------self.count = count
----def __await__(self):
--------yield from range(self.count)
这样你就不是用 generator based coroutine 来暂停执行了,但这也不是 native coroutine 了。

可见这完全是语言的限制,因为 yield 后面可以跟任意的值,yield from 可以接任意 generator 对象,而 await 却只能接 awaitable 对象。

所以纠结 native coroutine 为什么不能「暂停执行并强制性返回给事件循环」没多大意义,因为你实际在编写最底层调用的那句代码时,肯定要用 yield 或 yield from。但如果不是编写框架,你基本上只需要写到 await native_coroutine 这层的代码。
2016-05-23 15:28:29 +08:00
回复了 hellogbk 创建的主题 macOS 你们的 MAC QQ 掉线吗?
节能器里把「唤醒以供网络访问」关了就行了,否则会不定期把另一台 mac 的 qq 踢下线
有个东西叫缓冲区溢出,没有做好检查的话,会一直往后写,导致栈被修改掉。而函数的返回地址也在栈里,就导致返回时跳到其他区域,就能执行攻击代码了。
你的索引可能不能用来优化这个查询,导致需要全表扫描。你 explain 一下就知道原因了。
1 ... 7  8  9  10  11  12  13  14  15  16 ... 55  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2651 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 33ms · UTC 06:54 · PVG 14:54 · LAX 22:54 · JFK 01:54
Developed with CodeLauncher
♥ Do have faith in what you're doing.