小编P D*_*ddy的帖子

您可以在 Python 类型注释中指定方差吗?

你能发现下面代码中的错误吗?米皮不能。

from typing import Dict, Any

def add_items(d: Dict[str, Any]) -> None:
    d['foo'] = 5

d: Dict[str, str] = {}
add_items(d)

for key, value in d.items():
    print(f"{repr(key)}: {repr(value.lower())}")
Run Code Online (Sandbox Code Playgroud)

当然,Python 发现了错误,这有助于通知我们'int' object has no attribute 'lower'. 太糟糕了,直到运行时它才能告诉我们这一点。

据我所知, mypy 没有捕获此错误,因为它允许 参数的参数dadd_items协变的。如果我们只阅读字典,那就有意义了。如果我们只是读取,那么我们会希望参数是协变的。如果我们准备读取任何类型,那么我们应该能够读取字符串类型。当然,如果我们只是阅读,那么我们应该将其输入为typing.Mapping.

由于我们正在编写,所以我们实际上希望参数是逆变的。例如,某人传入 a 是完全有意义的Dict[Any, Any],因为它完全能够存储字符串键和整数值。

如果我们要进行读写,就别无选择,只能让参数保持不变。

有没有办法指定我们需要什么样的方差?更好的是, mypy 是否足够复杂,以至于期望它通过静态分析确定方差应该是合理的,并且这应该作为错误归档?或者 Python 中类型检查的当前状态根本无法捕获这种编程错误?

python typing covariance mypy

6
推荐指数
1
解决办法
6003
查看次数

避免 Python 中的模块命名空间污染

特尔;博士:将实现细节保留在模块命名空间之外的最简洁方法是什么?

已经有许多关于这个主题的类似问题,但相对于现代工具和语言功能,似乎没有一个令人满意的答案。

我正在设计一个 Python 包,我想保持每个模块的公共接口干净,只公开预期的内容,隐藏实现细节(尤其是导入)。

多年来,我看到了许多技术:

别担心。只需记录如何使用您的包,让其消费者忽略实现细节。

在我看来,这太可怕了。一个设计良好的界面应该很容易被发现。公开可见的实现细节会使界面更加混乱。即使作为包的作者,我也不想在它暴露太多时使用它,因为它会使自动完成功能变得不那么有用。

在所有实现细节的开头添加下划线。

这是一个很好理解的约定,大多数开发工具都足够聪明,至少可以将下划线前缀的名称排序到自动完成列表的底部。如果你有少量的名字来这样处理它工作得很好,但随着名字的数量增加,它变得越来越乏味和丑陋。

以这个相对简单的导入列表为例:

import struct

from abc    import abstractmethod, ABC
from enum   import Enum
from typing import BinaryIO, Dict, Iterator, List, Optional, Type, Union
Run Code Online (Sandbox Code Playgroud)

应用下划线技术,这个相对较小的导入列表变成了这个怪物:

import struct as _struct

from abc    import abstractmethod as _abstractmethod, ABC as _ABC
from enum   import Enum as _Enum
from typing import (
    BinaryIO as _BinaryIO,
    Dict     as _Dict,
    Iterator as _Iterator,
    List     as _List,
    Optional as _Optional,
    Type     as _Type,
    Union    as _Union
)
Run Code Online (Sandbox Code Playgroud)

现在,我知道这个问题可以通过从不进行 …

python namespaces package

5
推荐指数
1
解决办法
311
查看次数

奇怪的扩展方法重载决议

我无法让编译器解决扩展方法的正确重载问题.我解释的最好方法是使用一些代码.这是一个演示问题的LINQPad脚本.由于我遇到的问题,这将无法编译:

void Main(){
    new Container<A>().Foo(a=>false);
}

interface IMarker{}
class A : IMarker{
    public int AProp{get;set;}
}
class B : IMarker{
    public int BProp{get;set;}
}
class Container<T>{}

static class Extensions{
    public static void Foo<T>(this T t, Func<T, bool> func)
        where T : IMarker{
        string.Format("Foo({0}:IMarker)", typeof(T).Name).Dump();
    }
    public static void Foo<T>(this Container<T> t, Func<T, bool> func){
        string.Format("Foo(Container<{0}>)", typeof(T).Name).Dump();
    }
}
Run Code Online (Sandbox Code Playgroud)

我得到的错误是:

以下方法或属性之间的调用不明确:' Extensions.Foo<Container<A>>(Container<A>, System.Func<Container<A>,bool>)'和' Extensions.Foo<A>(Container<A>, System.Func<A,bool>)'

在我看来,它根本不含糊.第一种方法不接受a Container<T>,只接受a IMarker.似乎通用约束不能帮助解决重载,但在这个版本的代码中,它们似乎确实如下:

void Main(){
    new A().Bar();
    new A().Foo(a=>a.AProp == …
Run Code Online (Sandbox Code Playgroud)

c# extension-methods overload-resolution

4
推荐指数
1
解决办法
381
查看次数

SQL Server:查找错误数据

如何选择除我CONVERT在其中一列上调用错误的行之外的所有行?

例如,我这样做:

SELECT rowid 
FROM batchinfo 
WHERE CONVERT(DATE, reporttime, 101) between '2010-07-01' and '2010-07-31';
Run Code Online (Sandbox Code Playgroud)

我收到一些价值的错误.我有两个问题:

  1. 如何跳过有错误的行?
  2. 我怎样才能得到只有有错误的行?

sql sql-server

3
推荐指数
1
解决办法
1940
查看次数

C#:抽象类中的抽象和非抽象方法?

我不确定我写的代码是否有意义.这是一般的想法:

我有一个Parser类,它将采用不同类型的文档.根据类型,我将以不同方式解析文档.

所以假设我有两种类型的文档,A和B.如果我需要扩展程序来处理其他类型,工厂模式似乎是一个非常好的方法,所以我将有一个抽象类.

abstract class Parser
{
   ...
   public void common_method() {
      // something common that all parsers will use
      // like file IO
   }

   // derived classes will override this
   public abstract void specific_method();
}

class A_Parser : Parser
{
   ...
}

class B_Parser : Parser
{
   ...
}
Run Code Online (Sandbox Code Playgroud)

我想知道的问题是我在抽象的Parser中声明了抽象方法和非抽象方法.编译器似乎没有抱怨,它似乎仍然正常工作.

这不标准吗?也许有更好的方法来设计它?

c# design-patterns

3
推荐指数
1
解决办法
8713
查看次数