[分享] C++和Python的相似處
本文大部份內容來自此網頁:
C++ Has Become More Pythonic
http://preshing.com/20141202/cpp-has-become-more-pythonic/
---------------------------
我以前也是覺得C++的語法看起來很複雜很討厭的人。
不過C++這幾年變了很多,C++11 和 C++14 加了很多新語法進去。
連C++的老爸 Bjarne Stroustrup
http://www.stroustrup.com/C++11FAQ.html#think 都說:
“It feels like a new language.”
該怎麼說呢?語法上愈來愈簡潔,愈來愈python化了...
不知道是python影響C++還是C++影響python?
以下就大致列出python跟C++的共同點。
### 語法 (Literals) ###
Python從2008年開始引進字面輸入二進位值(binary literals)。
gcc從2007年就支援(雖然C standard從來沒把這個加進去)。
C++是直到C++14
http://en.cppreference.com/w/cpp/language/integer_literal
才正式支援:
static const int primes = 0b1010000010001010001010;
當字串中有**'\\'**的時候,以前你可能得這樣寫:
const char* path = "(c:\\this\\string\\has\\backslashes)";
C++11 http://en.cppreference.com/w/cpp/language/string_literal
開始可以字面輸入原始字串(raw string literals)。
const char* path = R"(c:\this\string\has\backslashes)";
Python則是1998年就支援了。
### 有範圍根據的 for 迴圈(Range-Based For Loops) ###
Python裡要在同一個物件裡用迴圈把其中元素一一取出的話很簡單:
for x in myList:
print(x)
古早的C++寫起來很累贅
// array
for (int i=0; i<10; ++i) std::cout<< A[i] << ' ';
// vector(我討厭這種寫法...)
for(std::vector<T>::iterator it = v.begin(); it != v.end(); ++it) {
/* std::cout << *it; ... */
}
http://en.cppreference.com/w/cpp/language/range-for
C++11開始你就能優雅地寫for loop:
std::vector<int> v = {0, 1, 2, 3, 4, 5};
for(const int &i : v) // access by const reference
std::cout << i << ' ';
std::cout << '\n';
for(auto i: v) // access by value, the type of i is int
std::cout << i << ' ';
std::cout << '\n';
for(auto&& i: v) // access by reference, the type of i is int&
std::cout << i << ' ';
std::cout << '\n';
for(int n: {0, 1, 2, 3, 4, 5}) // the initializer may be a braced-init-list
std::cout << n << ' ';
std::cout << '\n';
int a[] = {0, 1, 2, 3, 4, 5};
for(int n: a) // the initializer may be an array
std::cout << n << ' ';
std::cout << '\n';
for(int n: a) std::cout << 1 << ' '; // the loop variable need not be used
std::cout << '\n';
### 自動指定型別 Auto ###
Python有個方便的地方就是不用理會變數到底該用怎樣的型別(data type),
會自動幫你決定或改變。
C++以前可不是這樣,但是C++11
http://en.cppreference.com/w/cpp/language/auto
開始多了自動推斷類型的語法:
auto x = "Hello world!";
std::cout << x;
就算是有函式重載(function overloading)的情況下,
呼叫函式時編譯器也會對於auto自動判別的型別指到相對應的函式去。
C++14更方便,連自動決定函式的回傳型別(Function return type deduction)
https://en.wikipedia.org/wiki/C%2B%2B14#Function_return_type_deduction
都能辦到了。
auto Correct(int i) {
if (i == 1)
return i; // return type deduced as int
else
return Correct(i-1)+i; // ok to call it now
}
auto Wrong(int i) {
if (i != 1)
return Wrong(i-1)+i; // Too soon to call this. No prior return statement.
else
return i; // return type deduced as int
}
### Tuples ###
Python很久就有tuple這個能把不同型別的變數包在一起又不能修改的型別。
triple = (5, 6, 7)
print(triple[0])
C++11開始也有了,甚至直接挑明這是跟Python致敬。
auto triple = std::make_tuple(5, 6, 7);
std::cout << std::get<0>(triple);
Python可以把tuple拆開
x, y, z = triple
C++11當然也可以
std::tie(x, y, z) = triple;
### 統一初始化 (Uniform Initialization) ###
Python可以當初始一個List類型時就把元素加進去,之後想增加也行。
Dictionary也可以這樣搞。
myList = [6, 3, 7, 8]
myList.append(5);
myDict = {5: "foo", 6: "bar"}
print(myDict[5])
C++11 http://www.stroustrup.com/C++11FAQ.html#init-list 開始,
vector、std::map 和 unordered_map也可以這樣搞了
auto myList = std::vector<int>{ 6, 3, 7, 8 };
myList.push_back(5);
auto myDict
= std::unordered_map<int, const char*>{ { 5, "foo" }, { 6, "bar" } };
std::cout << myDict[5];
### Lambda 表達式 (Lambda Expressions) ###
Python的Lambda是很神奇的東西...
myList.sort(key = lambda x: abs(x))
C++11 http://www.stroustrup.com/C++11FAQ.html#lambda
居然也有了...
(可我還是比較喜歡函式指標阿....)
std::sort(myList.begin(), myList.end(), [](int x, int y){ return std::abs(x) < std::abs(y); });
### Standard Algorithms ###
Python可以用內建的filter函式把符合條件的元素複製出來...
result = filter(lambda x: x >= 0, myList)
C++11 http://en.cppreference.com/w/cpp/algorithm/copy
的 std::copy_if有著相似的功能...
(怎麼突然有種好神奇的感覺?)
auto result = std::vector<int>{};
std::copy_if(myList.begin(), myList.end(), std::back_inserter(result), [](int x){ return x >= 0; });
### Parameter Packs ###
Python這個功能我還真沒用過,實際用法可以參考這裡
http://hangar.runway7.net/python/packing-unpacking-arguments
def func1(x, y, z):
print x
print y
print z
def func2(*args):
# Convert args tuple to a list so we can modify it
args = list(args)
args[0] = 'Hello'
args[1] = 'awesome'
func1(*args)
func2('Goodbye', 'cruel', 'world!')
# Will print
# > Hello
# > awesome
# > world!
C++11 也能這樣做
http://www.stroustrup.com/C++11FAQ.html#variadic-templates
template <typename... T> auto foo(T&&... args) {
return std::make_tuple(args...);
}
...
auto triple = foo(5, 6, 7);
看到這裡,是不是覺得C++變得愈來愈優雅了?
--
※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 90.41.1.211
※ 文章網址: https://www.ptt.cc/bbs/C_and_CPP/M.1462301210.A.9FC.html
※ 編輯: wtchen (90.41.1.211), 05/04/2016 02:56:44
推
05/04 09:26, , 1F
05/04 09:26, 1F
推
05/04 10:06, , 2F
05/04 10:06, 2F
→
05/04 10:06, , 3F
05/04 10:06, 3F
→
05/04 10:07, , 4F
05/04 10:07, 4F
→
05/04 10:28, , 5F
05/04 10:28, 5F
拿掉了,因為本來是用kramdown寫的。
推
05/04 10:44, , 6F
05/04 10:44, 6F
推
05/04 10:51, , 7F
05/04 10:51, 7F
→
05/04 11:28, , 8F
05/04 11:28, 8F
→
05/04 14:11, , 9F
05/04 14:11, 9F
→
05/04 14:11, , 10F
05/04 14:11, 10F
→
05/04 14:13, , 11F
05/04 14:13, 11F
→
05/04 14:13, , 12F
05/04 14:13, 12F
→
05/04 14:33, , 13F
05/04 14:33, 13F
→
05/04 14:33, , 14F
05/04 14:33, 14F
→
05/04 14:34, , 15F
05/04 14:34, 15F
→
05/04 14:38, , 16F
05/04 14:38, 16F
→
05/04 14:39, , 17F
05/04 14:39, 17F
※ 編輯: wtchen (90.41.1.211), 05/04/2016 15:27:43
→
05/04 15:37, , 18F
05/04 15:37, 18F
推
05/04 15:58, , 19F
05/04 15:58, 19F
推
05/04 15:59, , 20F
05/04 15:59, 20F
→
05/04 16:25, , 21F
05/04 16:25, 21F
→
05/04 16:26, , 22F
05/04 16:26, 22F
→
05/04 16:31, , 23F
05/04 16:31, 23F
→
05/04 16:32, , 24F
05/04 16:32, 24F
→
05/04 16:34, , 25F
05/04 16:34, 25F
→
05/04 16:34, , 26F
05/04 16:34, 26F
→
05/04 16:36, , 27F
05/04 16:36, 27F
→
05/04 16:38, , 28F
05/04 16:38, 28F
→
05/04 16:43, , 29F
05/04 16:43, 29F
推
05/04 17:16, , 30F
05/04 17:16, 30F
推
05/04 21:38, , 31F
05/04 21:38, 31F
推
05/04 21:56, , 32F
05/04 21:56, 32F
推
05/04 22:43, , 33F
05/04 22:43, 33F
推
05/04 23:45, , 34F
05/04 23:45, 34F
推
05/05 00:11, , 35F
05/05 00:11, 35F
推
05/05 00:17, , 36F
05/05 00:17, 36F
推
05/05 04:38, , 37F
05/05 04:38, 37F
→
05/05 04:38, , 38F
05/05 04:38, 38F
推
05/05 07:18, , 39F
05/05 07:18, 39F
推
05/05 07:53, , 40F
05/05 07:53, 40F
→
05/05 10:51, , 41F
05/05 10:51, 41F
推
05/05 12:01, , 42F
05/05 12:01, 42F
推
05/05 12:07, , 43F
05/05 12:07, 43F
→
05/05 12:08, , 44F
05/05 12:08, 44F
→
05/05 12:22, , 45F
05/05 12:22, 45F
推
05/05 12:33, , 46F
05/05 12:33, 46F
→
05/05 12:34, , 47F
05/05 12:34, 47F
→
05/05 12:45, , 48F
05/05 12:45, 48F
→
05/05 12:45, , 49F
05/05 12:45, 49F
→
05/05 12:47, , 50F
05/05 12:47, 50F
→
05/05 12:47, , 51F
05/05 12:47, 51F
→
05/05 12:48, , 52F
05/05 12:48, 52F
推
05/05 16:02, , 53F
05/05 16:02, 53F
→
05/05 16:09, , 54F
05/05 16:09, 54F
→
05/05 16:10, , 55F
05/05 16:10, 55F
推
05/05 16:36, , 56F
05/05 16:36, 56F
→
05/05 16:36, , 57F
05/05 16:36, 57F
推
05/05 17:46, , 58F
05/05 17:46, 58F
推
05/05 19:01, , 59F
05/05 19:01, 59F
→
05/05 19:03, , 60F
05/05 19:03, 60F
→
05/05 19:04, , 61F
05/05 19:04, 61F
→
05/05 19:05, , 62F
05/05 19:05, 62F
→
05/05 19:19, , 63F
05/05 19:19, 63F
→
05/05 19:19, , 64F
05/05 19:19, 64F
推
05/05 19:45, , 65F
05/05 19:45, 65F
推
05/06 11:17, , 66F
05/06 11:17, 66F
→
05/06 11:23, , 67F
05/06 11:23, 67F
推
05/06 16:30, , 68F
05/06 16:30, 68F
推
05/06 19:34, , 69F
05/06 19:34, 69F
推
05/07 22:39, , 70F
05/07 22:39, 70F
推
05/07 22:41, , 71F
05/07 22:41, 71F
推
05/08 01:46, , 72F
05/08 01:46, 72F
推
05/16 02:53, , 73F
05/16 02:53, 73F
→
05/16 02:53, , 74F
05/16 02:53, 74F