首页   注册   登录
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python 学习手册
Python Cookbook
Python 基础教程
Python Sites
PyPI - Python Package Index
http://www.simple-is-better.com/
http://diveintopython.org/toc/index.html
Pocoo
值得关注的项目
PyPy
Celery
Jinja2
Read the Docs
gevent
pyenv
virtualenv
Stackless Python
Beautiful Soup
结巴中文分词
Green Unicorn
Sentry
Shovel
Pyflakes
pytest
Python 编程
pep8 Checker
Styles
PEP 8
Google Python Style Guide
Code Style from The Hitchhiker's Guide
V2EX  ›  Python

如何重写字符串的遍历方法?

  •  
  •   Morriaty · 34 天前 · 1958 次点击
    这是一个创建于 34 天前的主题,其中的信息可能已经有所发展或是发生改变。

    默认的遍历方式是

    for i in "为了让大家在 V2EX 上的时间更有效率":
         yield i
    
    ['为', '了', '让', '大', '家', '在', ' ', 'V', '2', 'E', 'X', ' ', '上', '的', '时', '间', '更', '有', '效', '率']
    

    但现在希望的方式是遇见连续的英文数字就合并

    for i in "为了让大家在 V2EX 上的时间更有效率":
         yield i
    
    ['为', '了', '让', '大', '家', '在', ' ', 'V2EX', ' ', '上', '的', '时', '间', '更', '有', '效', '率']
    

    当然,最简单的方式是写一个foreach函数,然后for i in foreach(string)

    只是想确认下是否可以直接重写字符串的遍历方法

    第 1 条附言  ·  34 天前

    貌似我表述的不够清楚,我不是不会写这个遍历函数,我是想重写str的__iter__方法,但不知道具体怎么做,大致逻辑入下

    import builtins
    
    
    class MyStr(str):
        def __iter__(self):
            # 不知道怎么改
            pass
    
    
    builtins.str = MyStr
    
    a = "测试Test test123结束"
    
    for i in a:
        print i
    
    
    ###预期输出
    测
    试
    Test
     
    test123
    结
    束
    
    21 回复  |  直到 2018-06-15 16:39:14 +08:00
        1
    shuianfendi6   34 天前
    re.compile("[a-zA-Z0-9]+|[^\x00-\xff]").findall(a)
        2
    changrui0608   34 天前
    感觉可以自定义一个类继承 str,然后自己重写相应的方法
    https://stackoverflow.com/questions/2673651/inheritance-from-str-or-int
        3
    F1024   34 天前
    "为了让大家在 V2EX 上的时间更有效率".split("")
        4
    linxiaoziruo   34 天前
    题主头像是谁
        5
    wangyongbo   34 天前
    for x in re.findall('[^A-Za-z\d]{1}|[A-Za-z\d]+', s):
    ... print x
        6
    crb912   34 天前 via Android
    Cpython 的字符串遍历,默认用了 yield 关键字?
        7
    polythene   34 天前
    @crb912 好像是用了 iterator 协议
        8
    crb912   34 天前 via Android
    @polythene yield 关键字,会让函数成为生成器 generator。
    不同点是,1. 生成器只能被迭代一次,迭代器 iterator 没有这种限制,2. 而且生成器的元素不会一次读入内存,而是会在调用逐个加载。它们的共同点都实现了可迭代协议__iter__方法,__next__方法。
    所以 yield 应该是你随手写的吧?
        9
    ccsiyu   34 天前
    写一个两层循环,在内层循环里用贪心法向前搜索能合并的单词

    实际上还是 O(n)
        10
    Morriaty   34 天前
    @changrui0608 是不是我表述的太差了,貌似只有你一个人理解了我的意思
    不过 SO 这个依然很麻烦,我必须修改所有的 str 赋值语句
    a = "xxx"
    改成
    a = MyStr("xxx")
        11
    Morriaty   34 天前
    @linxiaoziruo 长泽雅美
        12
    Morriaty   34 天前
    @shuianfendi6 @wangyongbo @ccsiyu 你们误会我意思了,详见 append
        13
    ccsiyu   34 天前
    @Morriaty 知道了,你知道算法,但是想 override 原来的方法。那就用一个子类继承 str 这个父类(不熟悉 python,根据上下文猜测的)然后 override 就行了
        14
    XYxe   34 天前
    ```python
    import cffi
    import ctypes


    class new_str_iterator():
    def __init__(self, s):
    self.index = 0
    self.s = s

    def __iter__(self):
    return self

    def __next__(self):
    '''你需要的功能'''


    def __new_str_iter__(obj_addr):
    obj = ctypes.cast(obj_addr, ctypes.py_object).value
    iter_obj = new_str_iterator(obj)
    ctypes.pythonapi.Py_IncRef(id(iter_obj))
    return id(iter_obj)


    ctypes.pythonapi.Py_IncRef.argtypes = [ctypes.c_size_t]
    ITER_FUNC = ctypes.CFUNCTYPE(ctypes.c_ssize_t, ctypes.c_ssize_t)
    cnew_str_iter = ITER_FUNC(__new_str_iter__)

    ffi = cffi.FFI()
    tp_iter_pointer = ffi.cast("size_t *", id(str) + 216)
    tp_iter_pointer[0] = ctypes.cast(cnew_str_iter, ctypes.c_void_p).value
    ```
        15
    XYxe   34 天前   ♥ 1
    格式乱了,看这里吧:
        16
    xiaket   34 天前
    根据 import this, 这种 magic 东西最好是显式的而不是隐式的, 所以推荐显式地定义 /import 一个类, 然后将你的逻辑放到这个类里面.
        17
    MrGba2z   33 天前
    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)
        18
    araraloren   33 天前
    不是可以用 wrapper/decorator/装饰器么,获取原函数的返回值,自己处理然后返回,同#17

    #!/usr/bin/perl6
    # your code goes here

    Str.^find_method("split").wrap(
    ----sub split(|c) {
    --------my @x = callwith(|c); # call Str::split with all arguments
    --------my @r = [];
    --------my ($i, $j) = (0, 0);
    --------my regex letter-number { <[a..z0..9]> }

    --------for @x -> $x {
    ------------if $x.lc ~~ /<letter-number>/ && $i > 0 && @r[$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
        19
    HaoC12   33 天前
    是不是可以通过栈来实现,判断进入的元素是不是字母,如果是在判断下一个,直到不是字母,出栈,下一个元素入栈。
        20
    excellentcx   33 天前
    难道不是正则表达式就可以完成的么???
        21
    darkjoker   33 天前
    @linxiaoziruo Masami 麻酱~
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   鸣谢   ·   实用小工具   ·   1107 人在线   最高记录 3541   ·  
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.1 · 19ms · UTC 23:48 · PVG 07:48 · LAX 16:48 · JFK 19:48
    ♥ Do have faith in what you're doing.
    沪ICP备16043287号-1