diff --git a/python/builtins.py b/python/builtins.py index 3435ea36..0c359574 100644 --- a/python/builtins.py +++ b/python/builtins.py @@ -86,11 +86,14 @@ def str::split(self, sep): res.append(self) return res -def str::index(self, sub): - for i in range(len(self)): - if self[i:i+len(sub)] == sub: - return i - return -1 +def str::format(self, *args): + if '{}' in self: + for i in range(len(args)): + self = self.replace('{}', str(args[i]), 1) + else: + for i in range(len(args)): + self = self.replace('{'+str(i)+'}', str(args[i])) + return self def str::strip(self, chars=None): chars = chars or ' \t\n\r' diff --git a/src/pocketpy.h b/src/pocketpy.h index 361f2bbd..6eeeceb7 100644 --- a/src/pocketpy.h +++ b/src/pocketpy.h @@ -390,11 +390,21 @@ inline void init_builtins(VM* _vm) { return VAR(self < obj); }); - _vm->bind_method<2>("str", "replace", [](VM* vm, ArgsView args) { + _vm->bind_method<-1>("str", "replace", [](VM* vm, ArgsView args) { + if(args.size() != 1+2 && args.size() != 1+3) vm->TypeError("replace() takes 2 or 3 arguments"); const Str& self = CAST(Str&, args[0]); const Str& old = CAST(Str&, args[1]); const Str& new_ = CAST(Str&, args[2]); - return VAR(self.replace(old, new_)); + int count = args.size()==1+3 ? CAST(int, args[3]) : -1; + return VAR(self.replace(old, new_, count)); + }); + + _vm->bind_method<1>("str", "index", [](VM* vm, ArgsView args) { + const Str& self = CAST(Str&, args[0]); + const Str& sub = CAST(Str&, args[1]); + int index = self.index(sub); + if(index == -1) vm->ValueError("substring not found"); + return VAR(index); }); _vm->bind_method<1>("str", "startswith", [](VM* vm, ArgsView args) { diff --git a/src/str.h b/src/str.h index 7e833168..f71a518a 100644 --- a/src/str.h +++ b/src/str.h @@ -224,19 +224,18 @@ struct Str{ return p - data; } - Str replace(const Str& old, const Str& new_) const { + Str replace(const Str& old, const Str& new_, int count=-1) const { std::stringstream ss; int start = 0; while(true){ int i = index(old, start); - if(i == -1){ - ss << substr(start, size - start); - break; - } + if(i == -1) break; ss << substr(start, i - start); ss << new_; start = i + old.size; + if(count != -1 && --count == 0) break; } + ss << substr(start, size - start); return ss.str(); } diff --git a/tests/04_str.py b/tests/04_str.py index a45b3133..4d48217e 100644 --- a/tests/04_str.py +++ b/tests/04_str.py @@ -75,4 +75,10 @@ assert str(num) == '6' # test Lo group names 测试 = "test" -assert 测试 == "test" \ No newline at end of file +assert 测试 == "test" + +assert "Hello, {}!".format("World") == "Hello, World!" +assert "{} {} {}".format("I", "love", "Python") == "I love Python" +assert "{0} {1} {2}".format("I", "love", "Python") == "I love Python" +assert "{2} {1} {0}".format("I", "love", "Python") == "Python love I" +assert "{0}{1}{0}".format("abra", "cad") == "abracadabra" \ No newline at end of file