Python中如何重写字符串的遍历方法?
默认的遍历方式是
for i in "为了让大家在 V2EX 上的时间更有效率":
yield i
[‘为’, ‘了’, ‘让’, ‘大’, ‘家’, ‘在’, ’ ', ‘V’, ‘2’, ‘E’, ‘X’, ’ ', ‘上’, ‘的’, ‘时’, ‘间’, ‘更’, ‘有’, ‘效’, ‘率’]
但现在希望的方式是遇见连续的英文数字就合并
for i in "为了让大家在 V2EX 上的时间更有效率":
yield i
[‘为’, ‘了’, ‘让’, ‘大’, ‘家’, ‘在’, ’ ', ‘V2EX’, ’ ', ‘上’, ‘的’, ‘时’, ‘间’, ‘更’, ‘有’, ‘效’, ‘率’]
当然,最简单的方式是写一个foreach函数,然后for i in foreach(string)
只是想确认下是否可以直接重写字符串的遍历方法
Python中如何重写字符串的遍历方法?
re.compile("[a-zA-Z0-9]+|[^\x00-\xff]").findall(a)
帖子没太看明白。字符串的遍历方法(比如__iter__)是Python内置类型的一部分,我们没法直接去改它。如果你是想自定义一个类,让它能像字符串一样被遍历,那很简单,在这个类里实现__iter__方法就行。
下面是一个例子,我创建了一个MyString类,它内部包装了一个字符串,但遍历时我想让每个字符重复两次。看代码:
class MyString:
def __init__(self, data):
self.data = str(data) # 确保数据是字符串
def __iter__(self):
# 遍历内部字符串的每个字符,并重复一次
for char in self.data:
yield char * 2
# 使用示例
my_str = MyString("hello")
for item in my_str:
print(item, end=' ') # 输出: hh ee ll ll oo
这里的关键就是__iter__方法,它必须返回一个迭代器。我用yield把它做成了一个生成器函数,这样写最省事。每次迭代时,它吐出的是原字符重复两次的结果。
如果你是想对普通的字符串str对象本身动手脚,那做不到,也不建议这么做。Python不允许你修改内置类型的这些核心方法。
总结一下,想自定义遍历行为就自己写个类并实现__iter__。
感觉可以自定义一个类继承 str,然后自己重写相应的方法
https://stackoverflow.com/questions/2673651/inheritance-from-str-or-int
“为了让大家在 V2EX 上的时间更有效率”.split("")
题主头像是谁
for x in re.findall(’[^A-Za-z\d]{1}|[A-Za-z\d]+’, s):
… print x
Cpython 的字符串遍历,默认用了 yield 关键字?
好像是用了 iterator 协议
yield 关键字,会让函数成为生成器 generator。
不同点是,1. 生成器只能被迭代一次,迭代器 iterator 没有这种限制,2. 而且生成器的元素不会一次读入内存,而是会在调用逐个加载。它们的共同点都实现了可迭代协议__iter__方法,__next__方法。
所以 yield 应该是你随手写的吧?
是不是我表述的太差了,貌似只有你一个人理解了我的意思
不过 SO 这个依然很麻烦,我必须修改所有的 str 赋值语句
a = "xxx"
改成
a = MyStr(“xxx”)
长泽雅美
你们误会我意思了,详见 append
知道了,你知道算法,但是想 override 原来的方法。那就用一个子类继承 str 这个父类(不熟悉 python,根据上下文猜测的)然后 override 就行了
python<br>import cffi<br>import ctypes<br><br><br>class new_str_iterator():<br> def __init__(self, s):<br> self.index = 0<br> self.s = s<br><br> def __iter__(self):<br> return self<br><br> def __next__(self):<br> '''你需要的功能'''<br><br><br>def __new_str_iter__(obj_addr):<br> obj = ctypes.cast(obj_addr, ctypes.py_object).value<br> iter_obj = new_str_iterator(obj)<br> ctypes.pythonapi.Py_IncRef(id(iter_obj))<br> return id(iter_obj)<br><br><br>ctypes.pythonapi.Py_IncRef.argtypes = [ctypes.c_size_t]<br>ITER_FUNC = ctypes.CFUNCTYPE(ctypes.c_ssize_t, ctypes.c_ssize_t)<br>cnew_str_iter = ITER_FUNC(__new_str_iter__)<br><br>ffi = cffi.FFI()<br>tp_iter_pointer = ffi.cast("size_t *", id(str) + 216)<br>tp_iter_pointer[0] = ctypes.cast(cnew_str_iter, ctypes.c_void_p).value<br>
根据 import this, 这种 magic 东西最好是显式的而不是隐式的, 所以推荐显式地定义 /import 一个类, 然后将你的逻辑放到这个类里面.
class Vstr(str):
def iter(self):
special_set = ‘abcdefghijklmnV2EX’
special_str = ‘’
for i in super().iter():
if i in special_set:
special_str += i
else:
if special_str:
yield special_str
special_str = ‘’
yield i
mystr = Vstr(‘为了让 abc 在 V2EX 上的 egg222 时间更有效率’)
for i in mystr:
print(i)
不是可以用 wrapper/decorator/装饰器么,获取原函数的返回值,自己处理然后返回,同#17
#!/usr/bin/perl6
# your code goes here
Str.^find_method(“split”).wrap(
----sub split(|c) {
--------my = callwith(|c); # call Str::split with all arguments
--------my = [];
--------my ($i, $j) = (0, 0);
--------my regex letter-number { <[a…z0…9]> }
--------for -> $x {
------------if $x.lc ~~ /<letter-number>/ && $i > 0 && [$i-1].lc ~~ /<letter-number>/ {
----------------r[$i-1] ~= $x;
------------} else {
----------------r[$i++] = $x;
------------}
--------}
--------r;
----}
);
my $ms = “为了让大家在 V2EX 上的时间更有效率”;
say $ms;
say $ms.split("").join("===");
https://ideone.com/FLlxXe
是不是可以通过栈来实现,判断进入的元素是不是字母,如果是在判断下一个,直到不是字母,出栈,下一个元素入栈。
难道不是正则表达式就可以完成的么???
Masami 麻酱~


