C++变得越来越像Python的证据

http://preshing.com/20141202/cpp-has-become-more-pythonic/

C++ Has Become More Pythonic

C++ has changed a lot in recent years. The last two revisions, C++11 and C++14, introduce so many new features that, in the words of Bjarne Stroustrup, “It feels like a new language.”

It’s true. Modern C++ lends itself to a whole new style of programming – and I couldn’t help noticing it has more of a Python flavor. Ranged-based for loops, type deduction, vector and map initializers,
lambda expressions. The more you explore modern C++, the more you find Python’s fingerprints all over it.

Was Python a direct influence on modern C++? Or did Python simply adopt a few useful constructs before C++ got around to it? You be the judge.

Literals

Python introduced binary literals in 2008. Now C++14
has them
. [Update: Thiago Macieira points out in the comments that GCC actually supported them
back in 2007.]

static const int primes = 0b10100000100010100010100010101100;

Python also introduced raw string literals back in 1998. They’re convenient when hardcoding a regular expression or a Windows path. C++11 added
the same idea with a slightly different syntax:

const char* path = R"(c:\this\string\has\backslashes)";

Range-Based For Loops

In Python, a for loop
always iterates over a Python object:

for x in myList:
    print(x)

Meanwhile, for nearly three decades, C++ supported only C-style for loops.
Finally, in C++11, range-based for loops were added:

for (int x : myList)
    std::cout << x;

You can iterate over a std::vector or
any class which implements the begin and end member
functions – not unlike Python’s iterator protocol. With range-based for loops, I often find myself wishing C++ had Python’s xrange function
built-in.

Auto

Python has always been a dynamically typed language. You don’t need to declare variable types anywhere, since types are a property of the objects themselves.

x = "Hello world!"
print(x)

C++, on the other hand, is not dynamically typed. It’s statically typed. But since C++11 repurposedthe auto keyword
for type deduction, you can write code that looks a lot like dynamic typing:

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

When you call functions that are overloaded for several types, such as std::ostream::operator<<or
a template function, C++ resembles a dynamically typed language even more. C++14 further fleshes out support for the auto keyword,
adding support for auto return
values
 and auto arguments to
lambda functions.

Tuples

Python has had tuples pretty much since the beginning. They’re nice when you need to package several values together, but don’t feel like naming a class.

triple = (5, 6, 7)
print(triple[0])

C++ added tuples to the standard library in C++11. The proposal even mentions Python as an inspiration:

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

Python lets you unpack a tuple into separate variables:

x, y, z = triple

You can do the same thing in C++ using std::tie:

std::tie(x, y, z) = triple;

Uniform Initialization

In Python, lists are a built-in type. As such, you can create a Python list using a single expression:

myList = [6, 3, 7, 8]
myList.append(5);

C++’s std::vector is
the closest analog to a Python list. Uniform initialization, new in C++11, now lets us create them using a single expression as well:

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

In Python, you can also create a dictionary with a single expression:

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

Similarly, uniform initialization also works on C++’s std::map and unordered_map:

auto myDict = std::unordered_map<int, const char*>{ { 5, "foo" }, { 6, "bar" } };
std::cout << myDict[5];

Lambda Expressions

Python has supported lambda functions since 1994:

myList.sort(key = lambda x: abs(x))

Lambda expressions were added in C++11:

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

In 2001, Python added statically nested scopes, which allow lambda functions to capture variables defined in enclosing functions:

def adder(amount):
    return lambda x: x + amount
...
print(adder(5)(5))

Likewise, C++ lambda expressions support a flexible set of capture rules, allowing you to do similar things:

auto adder(int amount) {
    return [=](int x){ return x + amount; };
}
...
std::cout << adder(5)(5);

Standard Algorithms

Python’s built-in filter function
lets you selectively copy elements from a list (though list comprehensions are preferred):

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

C++11 introduces std::copy_if,
which lets us use a similar, almost-functional style:

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

Other C++ algorithms that mimic Python built-ins include transformany_ofall_ofmin and max.
The upcoming ranges proposal has the potential to simplify such expressions further.

Parameter Packs

Python began supporting arbitrary argument lists in 1998. You can define a function taking a variable number of arguments, exposed as a tuple, and expand a tuple when
passing arguments to another function:

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

C++11 adds support for parameter packs. Unlike C-style variable arguments, but like Python’s arbitrary argument lists, the parameter pack has a name which represents
the entire sequence of arguments. One important difference: C++ parameter packs are not exposed
as a single object at runtime. You can only manipulate them through template metaprogramming at compile time.

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

Not all of the new C++11 and C++14 features mimic Python functionality, but it seems a lot of them do. Python is recognized as a friendly, approachable programming language. Perhaps some of its charisma has rubbed off?

What do you think? Do the new features succeed in making C++ simpler, more approachable or more expressive?

Tweet

? Fixing GCC‘s Implementation of memory_order_consume

Comments (29)

Patrice Roy· 6
days ago

From memory, Dave Abrahams made similar remarks as C++11 was stabilizing. I don‘t know if his texts are still online, sadly, but it became more and more clear that the simplification of syntax led to something we can call ?Pythonic?. In particular, the auto-deduced
function return types and arguments, which help tremendously in writing generic lambdas, were among the things he suggested and showed to be feasible and valuable.

A student of mine, a few years ago, remarked an interesting trend where, in his opinion, dynamic languages have a tendency to make their type systems more explicit (one could think of things such as TypeScript here, or some planned enhancements to JavaScript)
while languages with static type systems have a tendency to offer syntax simplifications (auto, var, lambdas, etc.); he saw both ?families? converging towards one another; I think he was onto something :)

Interesting post, as always. Cheers!

Reply

1 reply· active
2 days ago

@minonne· 2
days ago

Patrice, Dave Abrahams‘ s cpp-next.com seems dead but out there you can still look at it for examplehttps://web.archive.org/web/20131015192353/http:/...

Reply

Francisco Lopes· 6
days ago

The raw string literal syntax is not right. Nice article.

Reply

Martins· 6
days ago

Raw string literal example for C++11 is a bit wrong. It should have uppercase R, not lowercase r. And it should include parenthesis after and before " symbols:

R"(c:\this\string\has\backslashes)";

Reply

1 reply· active
6 days ago

Jeff Preshing· 6
days ago

Thanks. Fixed now!

Reply

passerby· 6
days ago

I think it‘s more of ML influence than Python.

Reply

Stan· 6
days ago

Does C++ have the useful Python feature that the assignment operator can be used in a function call so that the order of the arguments passed does not matter (matters less) by mapping the argument to the parameter variable name with the equal sign. This is
not the default parameter feature that both C++ and Python have but something else.

Reply

1 reply· active
5 days ago

Guest· 5
days ago

No, but there is a [proposal] (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4172.htm) to add that feature. In the
mean-time, if you really need named parameters, you can use the [boost library](http://www.boost.org/doc/libs/1_57_0/libs/parameter/doc/html/index.html).

Reply

fenbf· 6
days ago

in Visual Studio 2015 Preview there is even "Terse Range-Based For Loops"

basically you will be able to write: "for (elem : range)"

propsed for C++17

Reply

4 replies· active
5 days ago

Budai· 6
days ago

The terse form has been voted out, so its auto&& from now on.

Reply

Tom Lachecki· 6
days ago

n3994 was voted out? When? Can you provide some evidence?

Reply

Tom Lachecki· 6
days ago

Found it in the minutes from the last meeting - http://www.open-std.org/jtc1/sc22/wg21/docs/paper...

Reply

fenbf· 5
days ago

In favor: 8 Opposed: 43 abstain: 18

I thought it would pass since it was even implemented in VS...

Reply

fabio· 6
days ago

As an inside view from the committee I would say it is really more that python was faster in getting all the good stuff.

Other languages usage of a certain feature is seldom viewed as more than a hint that a feature might be a good idea, most features are motivated by solving problems that were Identified. Individual feature authors and reviewers might however be influenced by
other languages they know/like.

As far as language influence goes I would say that Haskell () is the strongest one, it keeps popping up as a reference during design discussions.

Python seems to be regarded as being good enough so that saying: "We should do x because Python does so" will not get you thrown from the room, unlike other languages I won‘t mention.

Reply

John· 6
days ago

Actually since python barely has any exclusive feature that weren‘t present in older languages like Common Lisp shouldn‘t we say that c++ has become more lispy?

Reply

4 replies· active
3 days ago

Ted· 6
days ago

This. Lisp had much of the functionality that is liked about python.

Reply

Catalin· 6
days ago

Lisp again ... a great language killed only by it‘s atrocious syntax. List is powerful but not Pythonic in any way.

Reply

knivil· 5
days ago

The title could be also: C++ has become more <Lisp/Scheme/Javascript/Haskell/...> . And Python is very similar to Lisp or Scheme. It has also something similar to call/cc. Maybe C++ will get something similar with resumable functions. And yes, I do not like
Python.

Reply

jfcaron· 6
days ago

There‘s even an internet aphorism regarding this:

https://en.wikipedia.org/wiki/Greenspun%27s_tenth...

Reply

rightfold· 5
days ago

Declaring variables and declaring their types are orthogonal. In JavaScript, for example you can declare variables but you cannot declare their types.

Reply

Lucidguppy· 5
days ago

I think this is a great idea for a book. It would give Pythonistas a good resource to write pythonic c++.

Reply

hammonjj· 5
days ago

A major difference between auto and python‘s variable declarations is that auto is a compile time deduction, so it isn‘t really dynamically typed.

Reply

1 reply· active
4 days ago

Jeff Preshing· 4
days ago

That is what I meant by "C++, on the other hand, is not dynamically typed."

Reply

Thiago Macieira· 5
days ago

GCC has supported binary literals as an extension since 2007 in both C and C++ modes. So we should instead say that Python adopted it after C and C++ had established the precedent.

The text about variable arguments is a bit misleading. Variable arguments to functions in general have been supported in C since the dawn of time (remember printf). Variable arguments to macros have been available since C99 and GCC implemented them as an extension
to C++ before C++11 standardised them. C++11 only added variable template parameters, which is just one of the aspects, albeit a very, very important one.

Reply

1 reply· active
4 days ago

Jeff Preshing· 4
days ago

I think a lot of C++ programmers still use printf (or some variant thereof), so I thought it wasn‘t necessary to mention the old syntax. Still, I‘ve revised the article a bit based on your feedback. Thanks.

Reply

@teh· 4
days ago

Yay, now do an article with the same features that have been in Perl for ages

Reply

@claudiordgz· 3
days ago

Yes, it does feel very Python. It makes me feel amazing for picking those two languages early on.

"What do you think? Do the new features succeed in making C++ simpler, more approachable or more expressive?"

Totally, the vector and map initializers are way beyond helpful. Plus the variadic templates are amazing and powerful tools.

Reply

Jochen· 1
day ago

Great article. IMHO it doesn‘t matter if C++ is now influenced by python or not. What the article shows is, that it is possible to mimic the python way. But as it is also obvious by all this exmaples: To write python code is easy, straight forward and ....
most important: concise - which also obvious C++ was and still is not. Just look at the first example of lambda expressions. In C++ it‘s littered with syntax instead of focusing on the task to achieve.

Reply

olimp· 13
hours ago

This article doesn‘t show that C++ became more Pythonic. It rather shows that C++ has became more Rubyish. Or Lispish. Or Javascriptish in some ways. Well, simply put - it included some features that some other languages had before. It wasn‘t really influenced
by Python more than any other language. :-)

时间: 2024-12-18 00:24:29

C++变得越来越像Python的证据的相关文章

(13)碎片化阅读只会让你变得越来越愚蠢

碎片化阅读正在令你变得越来越愚蠢 昨天下午我坐在回上海的火车上,掏出Kindle准备看<金字塔原理>. 当我开始看这本书的时候有两件非常可怕的事情发生了. 第一件事,我发现自己的大脑竟然像转不动了一样! 这本书的内容并不算过于的晦涩,但我理解起来非常的吃力,有些句子反复读了两三次仍然理解不了,仍然记不住. 可以明显的感觉到,大脑里负责进行复杂阅读和理解的部分像锈住了一样,不管我多么努力,这部分始终转不起来. 第二件事,我发现自己的注意力涣散的可怕! 看了两三段之后不由自主的就跑神了,等我回过神

人们正在变得越来越“懒”

随着科技的发展和时代的进步,许多之前觉得繁琐的事情都变得越发简单化.方便化.换句话说,人们正在变得越来越"懒". 万维钢曾将"量化"作为现代社会的三大思维方式之一,因此追求效率的现代人也更容易将时间和产出做出量化分析,从而产生巨大的"懒人经济"需求,从网购到快递服务,再到外卖,"懒人"们养活了越来越多的行业. 懒得做饭,于是有了外卖平台;懒得在路边等车,于是有了打车平台;懒得线下购物,于是有了电商平台;懒得自己找各种生活服务,

为什么Web前端变的越来越复杂,变得更加难学了

前端发展了也有些年头了,曾记得很多年前,聊起前端,都觉得是很简单,那个时候都没有前端工程师这个职位.可现在,前端已经逆袭了,已经不是原来的样子了,各种技术层出不穷,显的越来越高深莫测了.前端真的变得那么难了吗?在我看来,前端还是原来的前端,虽然有些关变换,但不应该像现在一样复杂. 框架太多了,新技术太多了 我们总是迷失在各种技术了,总是迷失在新技术带了的各种概念里.angularrect bootstrap等等,他们给我们带来便利的同时也给我们带来了麻烦.我们真的需要这些框架吗?学会了这些框架就

自学编程变得越来越简单之后,那些老程序员是有多恐慌?

我大学时期在一所注重硬件系统的学校中学习电子和计算机工程,中途我发现了网页开发这样东西,它彻底改变了我的人生轨迹. 我是否希望自己学的是计算机科学还是软件工程?那还用说?但是,考虑到我一直在自学关于编程的知识,而且事实证明当今世界上大多数程序员(约 69%)都是自学成才. 过去几年的经验使我确信,未来,编程是一项基本技能. 接下来我们就来谈谈吧. 所谓,编程基本上是指编写计算机执行的指令. 其实我故意把它定义的比较模糊的,主要是为了确保我的观点没有被遗漏. 软件/应用/网页开发是一项需要多年经验

贝叶斯思维 统计建模的Python学习法pdf

下载地址:网盘下载 编辑推荐 贝叶斯方法正在变得越来越常见与重要,但是却没有太多可以借鉴的资料来帮助初学者.基于Allen Downey在大学讲授的本科课程,本书的计算方法能帮助你获得一个良好的开端. 使用已有的编程技巧学习和理解贝叶斯统计 处理估计.预测.决策分析.假设的证据.假设检验等问题 从简单的例子开始,包括硬币问题.M&Ms豆问题.<龙与地下城>勇士投骰子问题.彩弹游戏和冰球比赛问题 学习计算方法,解决诸如SAT分数含义.模拟肾肿瘤和人体微生物建模问题 内容简介 <贝叶

笔记之Python网络数据采集

笔记之Python网络数据采集 非原创即采集 一念清净, 烈焰成池, 一念觉醒, 方登彼岸 网络数据采集, 无非就是写一个自动化程序向网络服务器请求数据, 再对数据进行解析, 提取需要的信息 通常, 有api可用, api会比写网络爬虫程序来获取数据更加方便. Part1 创建爬虫 Chapter1 初建网络爬虫 一旦你开始采集网络数据, 就会感受到浏览器为我们所做的所有细节, 它解释了所有的html, css, JavaScript 网络浏览器是一个非常有用的应用, 它创建信息的数据包, 发送

php、python、ruby——web脚本语言的比较

原文地址:http://klau.si/php-vs-python-vs-ruby 摘要 在过去几年里,在web应用程序编程中,脚本语言变得越来越受欢迎.本论文试图在如今三种最受欢迎的语言:PHP.Python和Ruby中找到其中的差异.优点.缺点.很明显,他们有他们自己的观点和支持,所以要陈述客观事实并满足一种科学的方法是一项困难的任务.这三种语言将在web应用程序环境进行有关历史.进化.流行程度.语法.语义.功能.安全性和性能方面做评估.最后,一个最终的结论将建议最有前途的一种语言. 1.介

Python中编码的详细讲解

看这篇文章前,你应该已经知道了为什么有编码,以及编码的种类情况 ASCII 占1个字节,只支持英文 GB2312 占2个字节,支持6700+汉字 GBK GB2312的升级版,支持21000+汉字 Shift-JIS 日本字符 ks_c_5601-1987 韩国编码 TIS-620 泰国编码 由于每个国家都有自己的字符,所以其对应关系也涵盖了自己国家的字符,但是以上编码都存在局限性,即:仅涵盖本国字符,无其他国家字符的对应关系.应运而生出现了万国码,他涵盖了全球所有的文字和二进制的对应关系, U

学python的一点感想

之前对python一点都不了解,选课的时候犹豫了好半天才选了它,然后就越发好奇会怎么上课.有没有趣,期待了一个暑假.果然没有让我失望,第一次上课,通过听老师对python的介绍,我对python产生了很多好感,又听老师提起我们会怎么样实践,就更兴奋了,还发现有很多大佬也选了这课--以上这些都让我觉得这课选得真值. 我专业和python没有什么关系,平时几乎没接触过编程语言,更别说python.在前两周学习.探索的过程中,我发现编程是没意思(这点以后可能会变),但是python很有趣,越来越喜欢它