基础语法
变量
所有变量都无需指明类型,统一作为一个可变指针对象,可以随时改变值和内存大小
顺序结构
list
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 35 36 37 38 39 40 41 a = [1 , 2 , 3 , 4 , 5 ] x = a[0 ] a[1 ] = 10 n = len (a) for v in a: pass for i in range (len (a)): pass a.append(6 ) a.insert(1 , 99 ) a.pop() a.pop(1 ) a.remove(3 ) b = a[1 :4 ] c = a[:3 ] d = a[::2 ] flag = 3 in a idx = a.index(3 ) a.sort() a.reverse()
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 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 #include <vector> #include <algorithm> using namespace std;int main () { int arr[5 ] = {1 , 2 , 3 , 4 , 5 }; int x = arr[0 ]; arr[1 ] = 10 ; int n_arr = sizeof (arr) / sizeof (arr[0 ]); for (int i = 0 ; i < n_arr; i++) {} for (int v : arr) {} vector<int > v = {1 , 2 , 3 , 4 , 5 }; int y = v[0 ]; v[1 ] = 10 ; int n_vec = v.size (); for (int i = 0 ; i < v.size (); i++) {} for (int x : v) {} v.push_back (6 ); v.insert (v.begin () + 1 , 99 ); v.pop_back (); v.erase (v.begin () + 1 ); bool found = find (v.begin (), v.end (), 3 ) != v.end (); sort (v.begin (), v.end ()); reverse (v.begin (), v.end ()); return 0 ; }
很显然两个语言都是T.method,function(T)这样混着用的,真的不好记啊
当然也可以解释说function是作为外部函数,并非单独一个数据结构的对象
看得出来python的index也是左闭右开的
tuple
1 2 3 tup1=(1 ,2 ,3 ,4 ,5 ) tup2=(6 ,7 ,8 ,9 ,10 ) tup3=tup1+tup3
没什么好解释的,就是不可变的列表而已,相当于加了const,但是可以转换成list,元组之间也能连接
dict
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 35 36 37 38 d = {"apple" : 3 , "banana" : 5 , "cherry" : 2 } d2 = dict (a=1 , b=2 , c=3 ) x = d["apple" ] y = d.get("banana" ) z = d.get("orange" , 0 ) d["apple" ] = 10 d["orange" ] = 7 del d["banana" ]val = d.pop("cherry" ) val2 = d.pop("pear" , 0 ) for key in d: print (key, d[key]) for key, value in d.items(): print (key, value) if "apple" in d: print ("exists" ) keys = d.keys() values = d.values() items = d.items() d3 = {**d, **d2}
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 35 36 37 #include <map> #include <iostream> using namespace std;int main () { map<string, int > m; m["apple" ] = 3 ; m["banana" ] = 5 ; m.insert ({"cherry" , 2 }); int x = m["apple" ]; int y = m.at ("banana" ); m["apple" ] = 10 ; m.erase ("banana" ); for (auto &pair : m) { cout << pair.first << ": " << pair.second << endl; } auto it = m.find ("cherry" ); if (it != m.end ()) { cout << "Found cherry: " << it->second << endl; } return 0 ; }
dict 用hash table实现,故具有随机性,而map是用红黑树实现的,可以做到有序
set
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 35 s = {1 , 2 , 3 , 4 , 5 } s2 = set ([3 , 4 , 5 , 6 , 7 ]) s3 = set () s.add(6 ) s.update([7 , 8 ]) s.remove(2 ) s.discard(10 ) val = s.pop() s.clear() for x in s: print (x) a = {1 ,2 ,3 } b = {3 ,4 ,5 } union_set = a | b intersection_set = a & b diff_set = a - b symmetric_diff = a ^ b if 3 in a: print ("exists" ) if 10 not in a: print ("not exists" )
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 #include <set> #include <unordered_set> #include <iostream> using namespace std;int main () { set<int > s = {1 ,2 ,3 ,4 ,5 }; s.insert (6 ); s.erase (2 ); for (int x : s) cout << x << " " ; cout << endl; unordered_set<int > us = {3 ,4 ,5 ,6 ,7 }; us.insert (8 ); us.erase (5 ); for (int x : us) cout << x << " " ; cout << endl; if (s.find (3 ) != s.end ()) cout << "3 exists in set" << endl; return 0 ; }
只是比dict和map少了一个值的存储,因此数据结构仍然不变
控制语句
选择语句
1 2 3 4 5 6 7 8 x = 10 if x > 0 : y = 1 elif x == 0 : y = 0 else : y = -1
看得出来else if还是太长了,而switch case大多数时候是真的没有用
循环结构
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 for i in range (5 ): pass a = [1 , 2 , 3 ] for v in a: pass i = 0 while i < 5 : i += 1 for i in range (10 ): if i == 3 : continue if i == 7 : break
函数与模块
python函数不需要指定返回类型,return也是可选的
如果没写return或者return后没有东西,则返回None
其余的函数语法和cpp差不多
1 2 3 4 5 6 7 8 def printHello (): print ('hello' ) def add (a, b=0 ): return a + b x = add(3 , 4 ) y = add(5 )
模块
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 def square (x ): return x * x import math_utilsv = math_utils.square(5 ) from math_utils import squareresult = square(10 ) from math_utils import square as sqresult=sq(10 ) from math_utils import *result=square(10 ) import math_utils as mathv = math.square(5 )
oop
最值得一提的特征就是python没有public,protected,private这样的限定符,而是通过下划线来区分,
概览
python
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 class MyClass : def __init__ (self, value: int ): self .__value = value def get (self ) -> int : return self ._value def set (self, value: int ) -> None : self ._value = value from my_class import MyClassobj = MyClass(10 ) print (obj.get()) obj.set (20 ) print (obj.get())
python不使用隐式的this指针,而是要显式写明self,调用的时候则可以忽略self
对象也和变量一样直接用’='赋值即可
cpp
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 #ifndef MYCLASS_H #define MYCLASS_H class MyClass {public : MyClass (int v); ~MyClass (); int get () const ; void set (int v) ; private : int value; }; #endif
1 2 3 4 5 6 7 8 9 10 11 12 13 14 #include "MyClass.h" MyClass::MyClass (int v) : value (v) {} MyClass::~MyClass () {} int MyClass::get () const { return value; } void MyClass::set (int v) { value = v; }
1 2 3 4 5 6 7 8 9 10 #include <iostream> #include "MyClass.h" int main () { MyClass obj (10 ) ; std::cout << obj.get () << std::endl; obj.set (20 ); std::cout << obj.get () << std::endl; }
python做不到像cpp一样的类内声明和类外实现,只能用下面的例子所述直接添加方法和成员,但这样或许还方便一点,就不需要用到难用的cmake了
1 2 3 4 5 6 from my_class import MyClassdef add_double (): def double (self ): return self .x * 2 MyClass.double = double
构造函数
如果不指定__init__就只有一个默认为空的实现
1 2 3 4 5 6 class MyClass : def __init__ (self, value ): self .value = value obj = MyClass(10 ) print (obj.value)
析构函数
基本用不上,因为python内部就能实现垃圾回收
1 2 3 4 5 6 7 8 9 10 class MyClass : def __init__ (self, value ): self .value = value def __del__ (self ): print (f"MyClass({self.value} ) 被销毁" ) obj = MyClass(5 ) del obj
实例属性和类属性
实例属性 :每个对象独立,存储在实例字典中
类属性 :所有实例共享,存储在类字典中
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class MyClass : class_attr = 0 def __init__ (self, value ): self .instance_attr = value obj1 = MyClass(10 ) obj2 = MyClass(20 ) print (obj1.instance_attr) print (obj2.instance_attr) print (obj1.class_attr) print (obj2.class_attr) MyClass.class_attr = 5 print (obj1.class_attr) print (obj2.class_attr)
私有成员和公有成员
1 2 3 4 5 6 7 8 9 10 11 12 class MyClass : def __init__ (self ): self .public = 1 self ._protected = 2 self .__private = 3 obj = MyClass() print (obj.public) print (obj._protected) print (obj._MyClass__private)
公有,私有,静态方法
公有方法 :默认,无下划线,任何地方可调用
私有方法 :双下划线 __name,name mangling,限制外部访问
静态方法 :@staticmethod,不接收 self 或 cls,独立于实例和类
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 class MyClass : def public_method (self ): print ("公有方法" ) def __private_method (self ): print ("私有方法" ) @staticmethod def static_method (x, y ): return x + y obj = MyClass() obj.public_method() obj._MyClass__private_method() print (MyClass.static_method(2 ,3 ))
类的继承
私有成员和私有方法不会被继承,需要这样调用self._Parent__private_method()
构造函数默认不继承,需要重写,但可以调用基类的构造函数
不过构造函数的前导双下划线说明了他是私有成员不可被继承,也可以说是设计的一个巧思
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 class Animal : def speak (self ): print ("Animal speaks" ) class Dog (Animal ): def speak (self ): print ("Dog barks" ) dog = Dog() dog.speak() class Walker : def walk (self ): print ("Walking" ) class SuperDog (Dog, Walker): pass sd = SuperDog() sd.speak() sd.walk()
多态
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 class Animal : def speak (self ): print ("Animal speaks" ) class Dog (Animal ): def speak (self ): print ("Dog barks" ) class Cat (Animal ): def speak (self ): print ("Cat meows" ) def make_sound (obj ): obj.speak() make_sound(Dog()) make_sound(Cat())
也就是说同一个方法可以直接由子类继承并完成不同的实现,而cpp里必须得先写明该方法是virtual,子类中要写明override,相比起来麻烦了不少
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 35 36 #include <iostream> using namespace std;class Animal {public : virtual void speak () { cout << "Animal speaks" << endl; } virtual ~Animal () {} }; class Dog : public Animal {public : void speak () override { cout << "Dog barks" << endl; } }; class Cat : public Animal {public : void speak () override { cout << "Cat meows" << endl; } }; void make_sound (Animal* a) { a->speak (); } int main () { Dog d; Cat c; make_sound (&d); make_sound (&c); }
python工程详解
所谓工程,其实我指的只是本地各层级文件夹和文件之间python文件的相互导入而已
1 2 3 4 5 6 7 8 9 10 from same_source_file import testfrom .same_source_file import testfrom same_source_dir import testfrom same_source_dir import inner_file from same_source_dir.inner_file import test
模块的导入
1 2 3 4 5 6 7 8 9 10 11 12 from fastapi import FastAPIapp = FastAPI() import fastapiapp=fastapi.FastAPI() import fastapi as faapp=fa.FastAPI() from fastapi import FastAPI as faapp =fa()
看得出来各个写法各有各的好处,得看对应的工程文件的大小和规模因地制宜
内置函数
enumerate()
有两个参数: 迭代对象和索引起始位置,默认从零开始
1 2 3 4 5 6 7 8 9 10 11 12 13 14 with out.open ("w" , encoding="utf-8" ) as f: for i, p in enumerate (posts, 1 ): f.write(f"## 招聘 {i} \n\n" ) f.write(f"- Issue: #{p['issue' ]} \n" ) f.write(f"- 作者: {p['author' ]} \n" ) f.write(f"- 时间: {p['created_at' ]} \n" ) f.write(f"- 来源: {p['url' ]} \n\n" ) f.write(p["text" ]) f.write("\n\n---\n\n" )
看代码便知道,这个i就是我们要用的索引,p就是遍历对象内的元素,这里则是一个字典