C ++是如何变得更加Pythonic

1.前言

C ++是如何变得更加Pythonic

近年来,C ++发生了很大变化。最近的两个修订版本C ++ 11和C ++ 14引入了许多新功能,以Bjarne Stroustrup的话来说,“感觉就像是一种新语言。”

现代C ++赋予了一种全新的编程风格,不禁注意到它具有更多的Python风格。基于范围的循环,类型推导,向量和映射初始化器,lambda表达式。只要对C++的探索越多,就会发现借鉴Python的地方就越多。Python对现代C ++有直接影响吗?还是在C ++出现之前Python只是采用了一些有用的结构?我们一起来看看呗!

2.C++ VS Python不同

2.1常量

Python 在2008年引入了二进制文字。现在C++ 14中也开始添加了

<code>static const int primes = 0b10100000100010100010100010101100;/<code>

Python 在1998年还引入了原始字符串文字。在对正则表达式或Windows路径进行硬编码时,它们很方便。C ++ 11中做法就不同:

<code>const char* path = R"(c:\\\\backslashes)";/<code>

2.2基于范围的循环

在Python中,for循环总是遍历Python对象:

<code>for x in myList:
print(x)/<code>

同时,近三十年来,C ++仅支持C风格的for循环。最后,在C ++ 11中,添加了基于范围的for循环:

<code>for (int x : myList)
std::cout << x;/<code>

您可以遍历std::vector实现begin和end成员函数的一个或任何类-与Python的iterator协议不同。使用基于范围的for循环,真心希望C ++ 也可以像Python一样内置函数xrange。

2.3弱化语言类型

Python一直是一种动态类型化的语言。无需声明变量类型,因为类型是对象本身的属性。

<code>x = "Hello world!"
print(x)/<code>

另一方面,C ++不是动态输入的。它是静态类型的。但由于不是动态输入的。它是静态类型的。但由于自动类型推导,看起来就很像动态类型。

<code>auto x = "Hello world!";
std::cout << x;/<code>

当调用几种类型重载的函数(例如std::ostream::operator<

2.4元组

从一开始Python就已经拥有了很多元组。当我们需要将多个值打包在一起时,一个类命名就够啦

<code>triple = (5, 6, 7)
print(triple[0])/<code>

C ++将元组添加到C ++ 11中的标准库中。该提案甚至提到了Python的灵感:

<code>auto triple = std::make_tuple(5, 6, 7);
std::cout << std::get<0>(triple);/<code>

Python则可以将元组解压缩为单独的变量:

<code>x, y, z = triple/<code>

我们可以使用C在C ++中执行相同的操作std::tie:

<code>std::tie(x, y, z) = triple;/<code>

2.5统一初始化

在Python中,列表是内置类型。这样就可以使用单个表达式创建Python列表:

<code>myList = [6, 3, 7, 8]
myList.append(5);/<code>

C++ std::vector是最接近Python列表的产物。统一初始化(C ++ 11中的新增功能)现在也使我们可以使用单个表达式来创建它们:

<code>auto myList = std::vector{ 6, 3, 7, 8 };
myList.push_back(5);
/<code>

在Python中,还可以使用单个表达式创建字典:

<code>myDict = {5: "foo", 6: "bar"}
print(myDict[5])/<code>

同样,统一初始化也适用于C ++ std::map和unordered_map:

<code>auto myDict = std::unordered_map{ { 5, "foo" }, { 6, "bar" } };
std::cout << myDict[5];
/<code>

2.6Lambda表达式

自1994年以来,Python就一直支持lambda函数:

<code>myList.sort(key = lambda x:abs(x))/<code>

Lambda表达式在C ++ 11中添加:

<code>std::sort(myList.begin(), myList.end(), [](int x, int y){ return std::abs(x) < std::abs(y); });/<code>

在2001年,Python添加了静态嵌套范围,该范围允许lambda函数捕获在函数内部中定义的变量

<code>def adder(amount):
return lambda x: x + amount
...
print(adder(5)(5))/<code>

同样,C ++ lambda表达式支持一组灵活的捕获规则,使您可以执行类似的操作:

<code>auto adder(int amount) {
return [=](int x){ return x + amount; };
}

...
std::cout << adder(5)(5);/<code>

2.7标准算法库

Python的内置filter函数可以让我们有选择地从列表中复制元素(尽管最好使用列表理解):

<code>result = filter(lambda x: x >= 0, myList)/<code>

C ++ 11 引入了 std::copy_if,它使我们能够使用相似的,几乎功能的样式:

<code>auto result = std::vector{};
std::copy_if(myList.begin(), myList.end(), std::back_inserter(result), [](int x){ return x >= 0; });
/<code>

其他C ++ 算法模拟Python的内置插件包括transform,any_of,all_of,min和max。即将发布的范围提案有可能进一步简化此类表达。

2.8参数列表

Python从1998年开始支持任意参数列表。您可以定义一个函数,该函数接受可变数量的参数(以元组形式显示),并在将参数传递给另一个函数时扩展元组:

<code>def foo(*args):
return tuple(*args)
...
triple = foo(5, 6, 7)/<code>

C ++ 11增加了对参数包的支持。与C风格的变量参数不同,但与Python的任意参数列表一样,参数包的名称表示整个参数序列。一个重要的区别:C ++参数包在运行时不会作为单个对象公开。但只有在编译时通过模板元编程来操作它们。

<code>template <typename...> auto foo(T&&... args) {
return std::make_tuple(args...);
}
...
auto triple = foo(5, 6, 7);/<typename...>/<code>

3.总结

并非所有新的C++ 11和C++ 14功能都模仿Python功能。Python被认为是一种友好的,易于接近的编程语言。也许它的一些魅力消失了?你怎么看?


分享到:


相關文章: