V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐学习书目
Learn Python the Hard Way
Python Sites
PyPI - Python Package Index
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
Morriaty
V2EX  ›  Python

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

  •  
  •   Morriaty · 2018-06-14 15:07:38 +08:00 · 4099 次点击
    这是一个创建于 2381 天前的主题,其中的信息可能已经有所发展或是发生改变。

    默认的遍历方式是

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

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

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

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

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

    第 1 条附言  ·  2018-06-15 00:10:36 +08:00

    貌似我表述的不够清楚,我不是不会写这个遍历函数,我是想重写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
    shuianfendi6
        1
    shuianfendi6  
       2018-06-14 15:50:55 +08:00
    re.compile("[a-zA-Z0-9]+|[^\x00-\xff]").findall(a)
    changrui0608
        2
    changrui0608  
       2018-06-14 18:50:19 +08:00
    感觉可以自定义一个类继承 str,然后自己重写相应的方法
    https://stackoverflow.com/questions/2673651/inheritance-from-str-or-int
    F1024
        3
    F1024  
       2018-06-14 19:06:08 +08:00
    "为了让大家在 V2EX 上的时间更有效率".split("")
    linxiaoziruo
        4
    linxiaoziruo  
       2018-06-14 19:44:53 +08:00
    题主头像是谁
    wangyongbo
        5
    wangyongbo  
       2018-06-14 20:04:32 +08:00
    for x in re.findall('[^A-Za-z\d]{1}|[A-Za-z\d]+', s):
    ... print x
    crb912
        6
    crb912  
       2018-06-14 20:52:58 +08:00 via Android
    Cpython 的字符串遍历,默认用了 yield 关键字?
    polythene
        7
    polythene  
       2018-06-14 20:56:37 +08:00
    @crb912 好像是用了 iterator 协议
    crb912
        8
    crb912  
       2018-06-14 21:39:16 +08:00 via Android
    @polythene yield 关键字,会让函数成为生成器 generator。
    不同点是,1. 生成器只能被迭代一次,迭代器 iterator 没有这种限制,2. 而且生成器的元素不会一次读入内存,而是会在调用逐个加载。它们的共同点都实现了可迭代协议__iter__方法,__next__方法。
    所以 yield 应该是你随手写的吧?
    ccsiyu
        9
    ccsiyu  
       2018-06-14 22:35:42 +08:00
    写一个两层循环,在内层循环里用贪心法向前搜索能合并的单词

    实际上还是 O(n)
    Morriaty
        10
    Morriaty  
    OP
       2018-06-14 23:59:21 +08:00
    @changrui0608 是不是我表述的太差了,貌似只有你一个人理解了我的意思
    不过 SO 这个依然很麻烦,我必须修改所有的 str 赋值语句
    a = "xxx"
    改成
    a = MyStr("xxx")
    Morriaty
        11
    Morriaty  
    OP
       2018-06-15 00:00:23 +08:00
    @linxiaoziruo 长泽雅美
    Morriaty
        12
    Morriaty  
    OP
       2018-06-15 00:11:29 +08:00
    @shuianfendi6 @wangyongbo @ccsiyu 你们误会我意思了,详见 append
    ccsiyu
        13
    ccsiyu  
       2018-06-15 02:10:00 +08:00
    @Morriaty 知道了,你知道算法,但是想 override 原来的方法。那就用一个子类继承 str 这个父类(不熟悉 python,根据上下文猜测的)然后 override 就行了
    XYxe
        14
    XYxe  
       2018-06-15 03:08:48 +08:00
    ```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
    ```
    XYxe
        15
    XYxe  
       2018-06-15 03:13:50 +08:00   ❤️ 1
    xiaket
        16
    xiaket  
       2018-06-15 07:12:16 +08:00
    根据 import this, 这种 magic 东西最好是显式的而不是隐式的, 所以推荐显式地定义 /import 一个类, 然后将你的逻辑放到这个类里面.
    MrGba2z
        17
    MrGba2z  
       2018-06-15 08:21:48 +08:00
    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)
    araraloren
        18
    araraloren  
       2018-06-15 09:16:18 +08:00
    不是可以用 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
    HaoC12
        19
    HaoC12  
       2018-06-15 10:54:55 +08:00
    是不是可以通过栈来实现,判断进入的元素是不是字母,如果是在判断下一个,直到不是字母,出栈,下一个元素入栈。
    excellentcx
        20
    excellentcx  
       2018-06-15 16:20:49 +08:00
    难道不是正则表达式就可以完成的么???
    darkjoker
        21
    darkjoker  
       2018-06-15 16:39:14 +08:00
    @linxiaoziruo Masami 麻酱~
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   973 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 19:57 · PVG 03:57 · LAX 11:57 · JFK 14:57
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.