How to change a string in a function when calling a function?
我不确定这是否可行,但是否有方法在从另一个函数调用函数时更改函数打印的字符串?我想这样做:
1 2 3 4 5 6 7 8 9 | def string(): print ("This cat was scared.") def main(): for words in string(): str.replace("cat","dog") # Print"The do was scared." main() |
根据流行的需求(好吧,一个人的好奇心…),下面是如何在调用函数之前更改函数中的字符串。
你不应该在实践中这样做。有一些使用代码对象的用例,但这并不是其中之一。另外,如果你做了一些不那么简单的事情,你应该使用像
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | import types def string(): print ("This cat was scared.") def main(): # A function object is a wrapper around a code object, with # a bit of extra stuff like default values and closure cells. # See inspect module docs for more details. co = string.__code__ # A code object is a wrapper around a string of bytecode, with a # whole bunch of extra stuff, including a list of constants used # by that bytecode. Again see inspect module docs. Anyway, inside # the bytecode for string (which you can read by typing # dis.dis(string) in your REPL), there's going to be an # instruction like LOAD_CONST 1 to load the string literal onto # the stack to pass to the print function, and that works by just # reading co.co_consts[1]. So, that's what we want to change. consts = tuple(c.replace("cat","dog") if isinstance(c, str) else c for c in co.co_consts) # Unfortunately, code objects are immutable, so we have to create # a new one, copying over everything except for co_consts, which # we'll replace. And the initializer has a zillion parameters. # Try help(types.CodeType) at the REPL to see the whole list. co = types.CodeType( co.co_argcount, co.co_kwonlyargcount, co.co_nlocals, co.co_stacksize, co.co_flags, co.co_code, consts, co.co_names, co.co_varnames, co.co_filename, co.co_name, co.co_firstlineno, co.co_lnotab, co.co_freevars, co.co_cellvars) string.__code__ = co string() main() |
。
如果这对您来说还不够糟糕:我提到代码对象是不可变的。当然,弦也是。但是足够深的覆盖,它们只是指向一些C数据的指针,对吗?再说一次,只有我们在使用cpython,但是如果我们……
首先,从Github上获取我的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | import ctypes import internals def string(): print ("This cat was scared.") def main(): for c in string.__code__.co_consts: if isinstance(c, str): idx = c.find('cat') if idx != -1: # Too much to explain here; see superhackyinternals # and of course the C API docs and C source. p = internals.PyUnicodeObject.from_address(id(c)) assert p.compact and p.ascii length = p.length addr = id(c) + internals.PyUnicodeObject.utf8_length.offset buf = (ctypes.c_int8 * 3).from_address(addr + idx) buf[:3] = b'dog' string() main() |
作为猜测:
- 您希望
string() 返回调用方可以使用的值,而不是将某些内容打印到屏幕上。所以你需要一个return 语句而不是print 调用。 - 您希望循环返回字符串中的所有单词,而不是所有字符,因此需要在字符串上调用
split() 。 - 你要替换每个单词中的内容,而不是文字
"cat" 中的内容。所以,你需要在word 上给replace 打电话,而不是在str 上。另外,replace 实际上并没有改变单词,它返回一个新的单词,你必须记住。 - 你想把这些字都打印出来。
小精灵
如果是这样:
1 2 3 4 5 6 7 8 9 10 | def string(): return"This cat was scared." def main(): for word in string().split(): word = word.replace("cat","dog") print(word, end=' ') print() main() |
。
这解决了你所有的问题。但是,它可以简化,因为您在这里并不真正需要
1 2 3 4 5 | def main(): for word in string().split(): if word =="cat": word ="dog" print(word, end=' ') print() |
但是,更简单地说,您可以在整个字符串上调用
1 2 | def main(): print(string().replace("cat","dog")) |
。
我认为您可能正在寻找的是使用默认参数调用函数的能力:
1 2 | def string(animal='cat'): print("This {} was scared.".format(animal)) |
1 2 | >>> string() This cat was scared. |
号
1 2 | >>> string('dog') This dog was scared. |
如果不向