我很好奇Python 3 中是否有一种方法可以提示__getattr__()Python 中方法的返回类型。
我有以下用于测试目的的虚拟代码:
class MyClass:
def __getattr__(self, item: str) -> str:
return 'test'
def __getattribute__(self, item: str) -> str:
return 'test'
c = MyClass()
print(c.hello, type(c.hello)) # test <class 'str'>
Run Code Online (Sandbox Code Playgroud)
不幸的是,Pycharm 无法解析hello上面的属性类型。我不确定,但我认为它目前是按Any类型处理的。
我还对上述代码提出了以下变体,但仍然无法使类型提示按预期工作:
from typing import Callable
ReturnsString = Callable[[], str]
class MyClass:
my_test_fn: ReturnsString = lambda self: 'hello'
__getattr__: ReturnsString = lambda self, _item: 'test'
__getattribute__: ReturnsString
c = MyClass()
# type hinting works as expected - return type is `str` …Run Code Online (Sandbox Code Playgroud) 我正在将 Python 3.6 与 PyCharm 一起使用,但令人沮丧的是,对于字典对象的特殊情况(具有固定键模式),不支持代码完成。
举例来说,我创建并尝试访问一个简单的字典对象,如下所示:
inventory = {'name': 'hammer', 'price': 2.3}
inventory['']
Run Code Online (Sandbox Code Playgroud)
当我将光标放在引号“ ”内并点击时,Ctrl + Space我会完成代码,并且 IDE 会正确建议字典对象中的所有可能的键。那太棒了!
但是,如果我尝试将其构建为返回相同字典对象的实用程序函数,例如使用用户提供的值但使用相同的字典键 - 那么我将不再获得代码完成!
def get_inventory(name: str, price: float):
return {'name': name, 'price': price}
inventory = get_inventory('hammer', 2.3)
inventory[''] # <- Pycharm can't offer any suggestions!
Run Code Online (Sandbox Code Playgroud)
有什么解决方法或解决方案吗?我已经搜索过类似的解决方案,但没有找到任何有效的解决方案。我知道我可以将其转换为一个类Inventory并以这种方式访问属性,但我不想这样做,原因如下:
dict对象是实现此目的最简单的方法任何关于如何让我的 IDE 通过识别此类对象中可能的键来协助代码完成的帮助或解决方案dict将不胜感激!
我正在开发一个当前支持Python 3.6+ 的库,但在如何在 Python 3.6 的模块中定义前向引用方面遇到了一些麻烦typing。我已经pyenv在本地 Windows 计算机上进行了设置,以便可以轻松地在不同的 Python 版本之间切换以进行本地测试,因为我的系统解释器默认为 Python 3.9。
这里的用例本质上是我尝试使用TypeVar有效的前向引用类型定义 a ,然后我可以将其用于类型注释目的。我已经确认当我在 3.7+ 上并直接从模块导入时,以下代码运行没有问题,但我无法在 Python 3.6 上获取它,因为我注意到前向引用不能用作某些参数原因。我还尝试将前向引用类型作为参数传递给,但遇到了类似的问题。ForwardReftypingTypeVarUnion
TypeVar以下是我试图在 python 3.6.0 以及更新版本(如 3.6.8)上工作的导入和定义- 我确实注意到我在次要版本之间遇到了不同的错误:
from typing import _ForwardRef as PyForwardRef, TypeVar
# Errors on PY 3.6:
# 3.6.2+ -> AttributeError: type object '_ForwardRef' has no attribute '_gorg'
# 3.6.2 or earlier -> AssertionError: assert isinstance(a, GenericMeta)
FREF = TypeVar('FREF', str, PyForwardRef)
Run Code Online (Sandbox Code Playgroud)
下面是我已经测试过的示例用法,它似乎按照 Python …
python type-hinting forward-declaration python-3.x python-typing
我正在尝试匹配类型注释,例如int | str,并使用正则表达式替换将它们替换为 string Union[int, str]。
期望的替换(之前和之后):
str|int|bool->Union[str,int,bool]Optional[int|tuple[str|int]]->Optional[Union[int,tuple[Union[str,int]]]]dict[str | int, list[B | C | Optional[D]]]->dict[Union[str,int], list[Union[B,C,Optional[D]]]]到目前为止我想出的正则表达式如下:
r"\w*(?:\[|,|^)[\t ]*((?'type'[a-zA-Z0-9_.\[\]]+)(?:[\t ]*\|[\t ]*(?&type))+)(?:\]|,|$)"
Run Code Online (Sandbox Code Playgroud)
您可以在 Regex Demo 上尝试一下。它并没有真正按照我想要的方式工作。到目前为止我注意到的问题:
到目前为止,它似乎无法处理嵌套的 Union 条件。例如,int | tuple[str|int] | bool似乎会导致一场匹配,而不是两次匹配(包括内部 Union 条件)。
正则表达式似乎]最后消耗了不必要的东西。
可能是最重要的一个,但我注意到 Python 中的模块似乎不支持正则表达式子例程re。这是我想到使用它的地方。
这主要是为了支持Python 3.7+ 的PEP 604语法,该语法需要前向声明(例如声明为字符串)注释才能支持,否则内置类型不支持该|运算符。
这是我想出的示例代码:
r"\w*(?:\[|,|^)[\t ]*((?'type'[a-zA-Z0-9_.\[\]]+)(?:[\t ]*\|[\t ]*(?&type))+)(?:\]|,|$)"
Run Code Online (Sandbox Code Playgroud)
对于 3.10 之前的 Python 版本,我使用__future__import 来避免出现以下错误: …
假设我有一个自定义用例,我需要动态创建或定义__init__数据类的方法。
例如,假设我需要像这样装饰它,@dataclass(init=False)然后修改__init__()方法以采用关键字参数,例如**kwargs. 但是,在kwargs对象中,我仅检查已知数据类字段是否存在,并相应地设置这些属性(下面的示例)
我想向我的 IDE (PyCharm) 键入提示,修改后的内容__init__仅接受列出的数据类字段作为参数或关键字参数。我不确定是否有办法解决这个问题,使用typing库或其他方式。我知道 PY3.11 已计划进行数据类转换,这可能会也可能不会满足我的要求(我的直觉是否定的)。
这是我正在使用的示例代码,这是一个基本案例,说明了我遇到的问题:
from dataclasses import dataclass
# get value from input source (can be a file or anything else)
def get_value_from_src(_name: str, tp: type):
return tp() # dummy value
@dataclass
class MyClass:
foo: str
apple: int
def __init__(self, **kwargs):
for name, tp in self.__annotations__.items():
if name in kwargs:
value = kwargs[name]
else:
# here …Run Code Online (Sandbox Code Playgroud) 我很好奇是否有一种惯用的方法来检查 a 是否chrono::DateTime<Utc>在时间范围内。在我的用例中,我只需要检查是否DateTime在当前时间的接下来的半小时内发生。
这是我到目前为止整理的内容。它使用timestamp()属性来获取我可以使用的原始(unix)时间戳。
use chrono::prelude::*;
use chrono::Duration;
#[inline(always)]
pub fn in_next_half_hour(input_dt: DateTime<Utc>) -> bool {
in_future_range(input_dt, 30 * 60)
}
/// Check if a `DateTime` occurs within the following X seconds from now.
pub fn in_future_range(input_dt: DateTime<Utc>, range_seconds: i64) -> bool {
let utc_now_ts = Utc::now().timestamp();
let input_ts = input_dt.timestamp();
let within_range = input_ts > utc_now_ts && input_ts <= utc_now_ts + range_seconds;
within_range
}
Run Code Online (Sandbox Code Playgroud)
我的测试用例是这样的:
fn main() {
let utc_now = Utc::now();
let …Run Code Online (Sandbox Code Playgroud) 所以我对 Rust 还很陌生,但来自 Python 的我发现这种情况总体来说非常令人困惑。
我喜欢 Python,因为如果你想对一段代码或只是一个函数调用进行计时,它非常容易:
print(timeit('a = "hee hee la le dah"; my_awesome_fn()', number = 1_000, globals=globals()))
Run Code Online (Sandbox Code Playgroud)
然后只需调用python script.py,或者更好的是,只需使用 IDE 中的绿色“运行”按钮即可调用脚本。但我在 Rust 中找不到等效的功能。
我知道 Rust 生态系统中有一个称为基准测试的概念,并且有一些类似的库就是criterion为此目的而存在的。问题是我对高等数学和统计学一无所知(本质上可以把我当作一个无能的白痴),而且我怀疑我能否从这样的框架或工具中受益匪浅。
所以我只是好奇如何tests在 Cargo 中使用来测试 Rust 中的代码块,甚至更好,甚至是函数调用。
例如,假设我在 Rust 中有类似的函数,我想多次调用它,然后检查性能如何变化等:
pub fn my_awesome_fn() {
trace!("getting ready to do something cool...");
std::thread::sleep(std::time::Duration::from_millis(500));
info!("finished!");
}
Run Code Online (Sandbox Code Playgroud)
我怎样才能简单地在 Rust 中计时这个函数my_awesome_fn?我想我正在寻找类似timeitpython 或类似的东西。理想情况下,它应该是直接使用的,并假设我对我正在做的事情一无所知。我很好奇是否有一个现有的库或框架可以用于此目的。
我正在处理需要 用单个空格替换多个空格的字符串 。看起来其中大多数只是人为错误,但我对处理此问题的理想方法感到好奇 - 最好是从&str到 的分配最少String。
到目前为止,这是我的方法如下:
const SPACE: &str = " ";
const TWO_SPACES: &str = " ";
/// Replace multiple spaces with a single space
pub fn trim_whitespace(s: &str) -> String {
let mut new_str: String = s.trim().to_owned();
while new_str.contains(TWO_SPACES) {
new_str = new_str.replace(TWO_SPACES, SPACE);
}
new_str
}
let result = trim_whitespace("Hello world! ");
assert_eq!(result, "Hello world!");
Run Code Online (Sandbox Code Playgroud)
编辑(10/2022):我有Python背景,做上面这样的事情是非常惯用的。例如, Python 中最快的版本(用单个空格替换多个空格)似乎是这样的:
const SPACE: &str = " ";
const TWO_SPACES: &str = " …Run Code Online (Sandbox Code Playgroud) 我试图理解这段代码是如何工作的,我们有:
people = ['Dr. Christopher Brooks', 'Dr. Kevyn Collins-Thompson',
'Dr. VG Vinod Vydiswaran', 'Dr. Daniel Romero']
def split_title_and_name(person):
return person.split()[0] + ' ' + person.split()[-1]
Run Code Online (Sandbox Code Playgroud)
所以我们得到了一个列表,这个方法应该基本上删除“Dr.”之间的所有内容。和姓氏。据我所知, split() 函数不能用于列表,而是用于字符串。所以 person 必须是一个字符串。但是,我们还向 person 添加了 [0] 和 [-1],这意味着我们应该获取“person”的第一个和最后一个字符,但我们得到的是第一个单词和最后一个单词。我无法理解这段代码!你能帮我理解一下吗?
非常感谢任何帮助,谢谢:)
python ×6
python-3.x ×5
rust ×3
string ×2
annotations ×1
autocomplete ×1
datetime ×1
getattr ×1
list ×1
pycharm ×1
regex ×1
replace ×1
rust-chrono ×1
syntax ×1
time ×1
timeit ×1
type-hinting ×1
whitespace ×1