python中基本語法
#輸入語句: >>> print'100+100=%d' %(100+100) 100+100=200 #輸出語句 >>> name = raw_input('input your name:') input your name:yinheyi >>> print('hello,%s' %name) hello,yinheyi
注意:raw_input()語句接收以後,預設儲存為str格式哦,如果要比較大小的話,記得轉為int型別。
>>> number = raw_input('input a number:') input a number:
12 >>> type(number) <type 'str'> >>> number = int(raw_input('input a number:')) input a number:12 >>> type(number) <type 'int'>
判斷與迴圈語句:
判斷語句:if…elif…else
>>> if a>= 50: ... print 'the number is big' ... elif a < 50: ... print'the number is small
' ... else: ... print "i don't know" ... the number is big迴圈語句: for…in
>>> sum = 0 >>> for number in range(101): ... sum = sum + number ... >>> print sum 5050
迴圈語句: while
>>> sum = 0 >>> n = 1 >>> while n < 101: ... sum = sum + n ... n
= n + 1 ... >>> print sum 5050
資料型別:列表、元組、字典、set
list: Python內建的一種資料型別是列表。lists是一個有序的集合,可以新增與刪除元素。
生成它是用 [] 就可以啦;
呼叫它時,用下標呼叫就可以啦(從0開始);如第一個元素,list[0];倒數第一個,list[-1];
可以用len()函式獲得list元素的個數;
在尾部新增用append(), 中間插入用insert();尾部刪除用pop();指定位置刪除為pop(i);
#定義一個friends的列表 >>> friends = ['xiaoming','ergou','sanmao'] >>> friends ['xiaoming', 'ergou', 'sanmao'] >>> friends[0] 'xiaoming' >>> friends[-1] 'sanmao' #新增與刪除 >>> friends.append('dapeng') >>> friends ['xiaoming', 'ergou', 'sanmao', 'dapeng'] >>> friends.insert(0,'diyi') >>> friends ['diyi', 'xiaoming', 'ergou', 'sanmao', 'dapeng'] >>> friends.pop() 'dapeng' >>> friends ['diyi', 'xiaoming', 'ergou', 'sanmao'] >>> friends.pop(2) 'ergou' >>> friends ['diyi', 'xiaoming', 'sanmao'] #替換 >>> friends[0] = 'wangbadan' >>> friends ['wangbadan', 'xiaoming', 'sanmao']
元組(tuple):tuple和list非常類似,但是tuple一旦初始化就不能修改。只要記住它不能修改就可以啦。很安全。
用 () 定義啊。
用下標呼叫,即tuple[1];
注意:它定義一個元素的tuple時,一定要這樣寫,如:name = (‘yin’,), 千萬別寫成 name = (‘yin’);
name = ('zhai','yin') >>> name ('zhai', 'yin') >>> name[0] 'zhai' >>> name[-1] 'yin'
字典(dictionary):它就是鍵-值對。如在C++語言中為map的容器。它的特點就是可以快速查詢,需要佔用大量的記憶體,記憶體浪費多。通過key計算位置的演算法稱為雜湊演算法(Hash)。
用 {} 定義dictionary哦;
隨著dictionary的增加,查詢時間不會增加的。
多次對一個key放入value,後面的值會把前面的值沖掉:
可以用 ‘key’in dic 或 dic.get(‘key’)的方法來檢視key是否存在。注意:dict提供的get方法,如果key不存在,可以返回None,或者自己指定的value,返回None的時候Python的互動式命令列不顯示結果。
刪除用: pop(key)。新增時,直接用key值的索引新增就可以的。
注意:ict內部存放的順序和key放入的順序是沒有關係的。
#定義一個dictionary; score = {'xiaoming':85,'xiaohong':62} >>> score {'xiaoming': 85, 'xiaohong': 62} #新增一個元素; >>> score['wangdan'] = 85 >>> score {'xiaoming': 85, 'xiaohong': 62, 'wangdan': 85} #刪除一個元素; >>> score.pop('xiaohong') 62 >>> score {'xiaoming': 85, 'wangdan': 85} #檢視key是否存在; >>> 'xiaoming' in score True #檢視一個key對應的值; >>> score.get('wangdan') 不存在時,返回一個自定義的值; 85>>> score.get('hehehe',-1) -1
set:set和dict類似,也是一組key的集合,但不儲存value。由於key不能重複,所以,在set中,沒有重複的key。set和dict的唯一區別僅在於沒有儲存對應的value,但是,set的原理和dict一樣,所以,同樣不可以放入可變物件。
要建立一個set,需要提供一個list作為輸入集合:
通過add(key)與remove(key)新增與刪除元素;
>>> s = set([1, 2, 3]) >>> s set([1, 2, 3])
注意,傳入的引數
[1, 2, 3]
是一個list,而顯示的set([1, 2, 3])
只是告訴你這個set內部有1,2,3這3個元素,顯示的[]不表示這是一個list。重複元素在set中自動被過濾:
>>> s = set([1, 1, 2, 2, 3, 3]) >>> s set([1, 2, 3])
新增與刪除
>>> s = set([1,2,3]) >>> s set([1, 2, 3]) >>> s.add('xiaoming') >>> s set([1, 2, 3, 'xiaoming']) >>> s.add(0) >>> s set([0, 1, 2, 3, 'xiaoming']) >>> s.remove(2) >>> s set([0, 1, 3, 'xiaoming'])
對於list與tuple的切片操作:
如list[:5]或list[0:5]表示第0,1,2,3,4個索引值;當然也可以為負的如,list[-2:0]等於list[-2:]即倒數第2、倒數第1個數;也可以跳著來哦:list[1:10:2],表示步長為2的。
list=range(100) #正著切片 >>> list[:10] [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] #負索引切片 list[-10:] [90, 91, 92, 93, 94, 95, 96, 97, 98, 99] #倒著切片 >>> list[10:0:-1] [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] >>> list[-1:-10:-1] [99, 98, 97, 96, 95, 94, 93, 92, 91] #跳著切片 >>> list[::10] [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
#tuple的切片 >>> (0, 1, 2, 3, 4, 5)[:3] (0, 1, 2) #字串的切片 >>> 'ABCDEFG'[:3] 'ABC' >>> 'ABCDEFG'[::2] 'ACEG'
它的迭代:
對於list、tuple還有字串都可以用 for…in 進行迭代哦;
而對於dictionary的話,也可以哦,只不過預設情況下,dict迭代的是key。如果要迭代value,可以用
for value in d.itervalues()
,如果要同時迭代key和value,可以用for k, v in d.iteritems()
。那麼,如何判斷一個物件是可迭代物件呢?方法是通過collections模組的Iterable型別判斷:
另外:Python內建的
enumerate
函式可以把一個list、tuple、字串本身變成索引-元素對,這樣就可以在for
迴圈中同時迭代索引和元素本身:>>> from collections import Iterable >>> isinstance('abc', Iterable) # str是否可迭代 True >>> isinstance([1,2,3], Iterable) # list是否可迭代 True >>> isinstance(123, Iterable) # 整數是否可迭代 False
列表生成式:很牛逼很方便的;它是用來建立list的生成式;我們舉例子看看哈:
生成1-10的list:
>>> range(1,11) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
生成 12、22、……102的list:
>>> list = [x*x for x in range(1,11)] >>> list [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
還可以再選擇一下哦:
>>> [x * x for x in range(1, 11)if x % 2 == 0] [4, 16, 36, 64, 100]
還可以兩層迴圈的:
>>> [m + n for m in 'ABC' for n in 'XYZ'] ['AX', 'AY', 'AZ', 'BX', 'BY', 'BZ', 'CX', 'CY', 'CZ']
生成器:
通過列表生成式,我們可以直接建立一個列表。但是,受到記憶體限制,列表容量肯定是有限的。而且,建立一個包含100萬個元素的列表,不僅佔用很大的儲存空間,如果我們僅僅需要訪問前面幾個元素,那後面絕大多數元素佔用的空間都白白浪費了。
所以,如果列表元素可以按照某種演算法推算出來,那我們是否可以在迴圈的過程中不斷推算出後續的元素呢?這樣就不必建立完整的list,從而節省大量的空間。在Python中,這種一邊迴圈一邊計算的機制,稱為生成器(Generator)。
建立方法1:第一種方法很簡單,只要把一個列表生成式的
[]
改成()
,就建立了一個generator:>>> L = [x * x for x in range(10)] >>> L [0, 1, 4, 9, 16, 25, 36, 49, 64, 81] >>> g = (x * x for x in range(10)) >>> g <generator object <genexpr> at 0x104feab40>
可以通過generator的.next()方法打印出來資料,另外也可以通過迭代哦,基本上我們都選擇for…in迭代方法。
建立方法2:通過特殊函式建立:如果一個函式定義中包含
yield
關鍵字,那麼這個函式就不再是一個普通函式,而是一個generator。#這是函式,輸出斐波那契數列 def fib(max): n, a, b = 0, 0, 1 while n < max: print b a, b = b, a + b n = n + 1 #這是generator,也是生成斐波那契數列; def fib(max): n, a, b = 0, 0, 1 while n < max: yield b a, b = b, a + b n = n + 1
注意:這裡,最難理解的就是generator和函式的執行流程不一樣。函式是順序執行,遇到return語句或者最後一行函式語句就返回。而變成generator的函式,在每次呼叫
next()
的時候執行,遇到yield
語句返回,再次執行時從上次返回的yield
語句處繼續執行。>>> def odd(): ... print 'step 1' ... yield 1 ... print 'step 2' ... yield 3 ... print 'step 3' ... yield 5 ... >>> o = odd() >>> o.next() step 1 1 >>> o.next() step 2 3 >>> o.next() step 3 5 >>> o.next() Traceback (most recent call last): File "<stdin>", line 1, in <module> StopIteration
函式的定義:
使用
def
語句,依次寫出函式名、括號、括號中的引數和冒號:
,然後,在縮排塊中編寫函式體,函式的返回值用return
語句返回。當用return 返回多個值時,返回的其實是一個tuple,即元組。
當一個語句塊是什麼也不做時,請用pass語句,如果為空的話,分出錯的。
如果函式沒有return或者只有單單的一個reuturn時 , 則返回none。
>>> def sum(x, y): ... sum = x + y ... return sum ... >>> print sum(1,2) 3
函式的引數問題:
函式可以有預設的引數:且函式的預設引數必須指向不變的物件(否則有邏輯錯誤)。
>>> def sum(x=1, y=2): ... return x + y ... >>> print sum() 3 >>> print sum(5) 7 >>> print sum(y=10) 11函式的可變引數:定義可變引數和定義list或tuple引數相比,僅僅在引數前面加了一個
*
號。在函式內部,引數numbers
接收到的是一個tuple,因此,函式程式碼完全不變。但是,呼叫該函式時,可以傳入任意個引數,包括0個引數。另外,Python允許你在list或tuple前面加一個*
號,把list或tuple的元素變成可變引數傳進去。#可變引數; >>> def sum(*numbers): ... sum = 0 ... for num in numbers: ... sum = sum + num ... return sum ... >>> sum(1,2,3) 6 >>> sum(1,2,3,4,5,6) 21 #把list或tuple元素變為可變引數傳入 >>> list = [1,2,3,4,5,6,7,8] >>> sum(*list) 36 >>> tuple = (1,3,4,75) >>> sum(*tuple) 83關鍵字引數:它也是可變的,僅僅在引數前面加了兩個
*
號。這些關鍵字引數在函式內部自動組裝為一個dict,Python允許你dictionary前面加**
號,把dictionary元素變成可變引數傳進去。。>>> def person(name, age, **other): ... print 'name:',name,'\n'\ ... 'age:',age,'\n'\ ... 'other:',other ... >>> person('xiaoming',18,sex='boy') name: xiaoming age: 18 other: {'sex': 'boy'}#把dictionar元素引數傳入 >>> dic = {'sex':'boy','tall':174} >>> person('xiaohong',22,**dic) name: xiaohong age: 22 other: {'tall': 174, 'sex': 'boy'}引數可以組合使用:在Python中定義函式,可以用必選引數、預設引數、可變引數和關鍵字引數,這4種引數都可以一起使用,或者只用其中某些,但是請注意,引數定義的順序必須是:必選引數、預設引數、可變引數和關鍵字引數。
另外,對於對於任意函式,都可以通過類似
func(*list, **dictionary)
的形式呼叫它,無論它的引數是如何定義的。對於遞迴函式:優點是定義簡單,邏輯清晰。但是有一個問題,使用遞迴函式需要注意防止棧溢位。在計算機中,函式呼叫是通過棧(stack)這種資料結構實現的,每當進入一個函式呼叫,棧就會加一層棧幀,每當函式返回,棧就會減一層棧幀。由於棧的大小不是無限的,所以,遞迴呼叫的次數過多,會導致棧溢位。
高階函式:就是能接收其它函式作為引數的函式。
#定義一個簡單的高階函式: >>> def add(x, y, f): ... return f(x) + f(y) #定義一個函式: def square(x): ... return x * x #呼叫高階函式: >>> add(5,6,square) 61map()高階函式
map()
函式接收兩個引數,一個是函式,一個是序列,map
將傳入的函式依次作用到序列的每個元素,並把結果作為新的list返回。#map函式分別用函式對傳入的元素做處理哦 >>> def square(x): ... return x*x >>> list = range(1,6) >>> list [1, 2, 3, 4, 5] >>> map(square, list) [1, 4, 9, 16, 25]reduce()高階函式
reduce把一個函式作用在一個序列[x1, x2, x3...]上,這個函式必須接收兩個引數,reduce把結果繼續和序列的下一個元素做累積計算,其效果就是:
reduce(f, [x1, x2, x3, x4]) = f(f(f(x1, x2), x3), x4).
#看看reduce,把[1, 2, 3, 4, 5] 變為 一個數:12345 >>> list [1, 2, 3, 4, 5] >>> def func(x, y): ... return x*10 + y ... >>> reduce(func, list) 12345filter()高階函式:
filter()
函式用於過濾序列。接收一個函式和一個序列。filter()
把傳入的函式依次作用於每個元素,然後根據返回值是True
還是False
決定保留還是丟棄該元素。def is_odd(n): return n % 2 == 1 filter(is_odd, [1, 2, 4, 5, 6, 9, 10, 15]) # 結果: [1, 5, 9, 15]排序演算法:sorted()函式
通常規定,對於兩個元素
x
和y
,如果認為x < y
,則返回-1
,如果認為x == y
,則返回0
,如果認為x > y
,則返回1
,這樣,排序演算法就不用關心具體的比較過程,而是根據比較結果直接排序。>>> sorted([123,34,654,24,623342,4546,32,0]) [0, 24, 32, 34, 123, 654, 4546, 623342]另外,它也可以接收一個函式,用於自定義的排序。
#定義一個倒序 >>> def reversed_cmp(x, y): ... if x > y: ... return -1 ... if x < y: ... return 1 ... return 0 ... >>> sorted([123,34,654,24,623342,4546,32,0],reversed_cmp) [623342, 4546, 654, 123, 34, 32, 24, 0]
返回函式這個變數:可以在一個函式裡面在定義一個一個函式,並返回這個函式名。
內部函式可以引用外部函式的引數和區域性變數,當內部函式名被返回時,外部函式的相關引數和變數都儲存在返回的函式中,這種稱為“閉包(Closure)”的程式結構擁有極大的威力。
來,舉例說明:
>>> def sum(x, y): ... def sum1(): ... return x + y ... return sum1 >>> f = sum(1, 2) >>> f <function sum1 at 0x7fab499ec8c0> #可以看出 f 為一個函式變數哦; >>> f() #返回這個函式的值; 3看下面兩個程式,仔細體會哦:
>>> def func1(): ... i = 1 ... def func2(): ... return i * i ... return func2 ... >>> f = func1() >>> f() 1與
>>> def func1(): ... i = 1 ... def func2(): ... return i * i ... i = 5 ... return func2 ... >>> f = func1() >>> f() 25看到了吧,返回的函式沒有立刻執行,而是直到呼叫了
f()
才執行。當執行時,i 變為了5。返回閉包時牢記的一點就是:返回函式不要引用任何迴圈變數,或者後續會發生變化的變數。
我們可以這樣做,讓它保證不受影響,這樣做的原因是因為已經把函式func2()的引數綁定了哦,為1。
>>> def func1(): ... i = 1 ... def func2(i): ... def func3(): ... return i * i ... return func3 ... return func2(i) ... i = 5 ... >>> f = func1() >>> f() 1
匿名函式:有些時候,不需要顯式地定義函式,直接傳入匿名函式更方便。
關鍵字lambda表示匿名函式,匿名函式有個限制,就是隻能有一個表示式,返回值就是該表示式的結果。
下面見識一下匿名函式哦:
>>> list = range(1,11) >>> list [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] >>> map(lambda x: x*x ,list) [1, 4, 9, 16, 25, 36, 49, 64, 81, 100]
函式裝飾器:
就是說,我們想對一個函式進行增強一些功能,但是呢,我們又不修改函式的定義,這種在程式碼執行期間動態增加功能的方式,稱之為“裝飾器”(Decorator)。本質上,decorator就是一個返回函式的高階函式。
一些額外的知識:函式物件都有一個__name__的屬性,可以得到函式名字。如:
>>> def hello(): ... print 'hello,world' ... >>> f = hello >>> hello.__name__ 'hello' >>> f.__name__ 'hello'看看下面實現的decorator:
#定義了一個函式的decorator; def f1(func): def f2(x, y): print 'i am using decorator' print 'call %s ' %func.__name__ return func(x, y) return f2 #用 @ 語法,把decorator置於函式的定義處,即邦定函式哦; @f1 def sum(x,y): return x + y #呼叫它: print sum(2,3)輸出為:
i am using decorator
call sum
5這是的@f1,就相當於 sum = f1(sum);
再看一個哈,我們可以給decorator傳入一定的引數哦:
# 定義一個函式的decorator; def f1(name): def f2(func): def f3(x, y): print 'my name is %s' %name print 'i am using decorator' print 'call %s ' %func.__name__ return func(x, y) return f3 return f2 #用 @語法哦; @f1('yinheyi') def sum(x,y): return x + y #呼叫它 print sum(2,3)輸出為:
my name is yinheyi
i am using decorator
call sum
5這是的@f1('yinheyi') 相當於 sum = f1('yinheyi') (sum);
對於上面的操作還有一些小問題:
上面的sum.__func__ 變為了f3,而不再是sum。所以:需要把原始函式sum的
__name__
等屬性複製到f3
函式中,否則,有些依賴函式簽名的程式碼執行就會出錯。Python內建的
functools.wraps
就是幹這個事的,所以, 在加入這個一句就可以啦:具體如下:# 新增這個庫 import functools def f1(name): def f2(func): @functools.wraps(func) #加入這個一個語句哦; def f3(x, y): print 'my name is %s' %name print 'i am using decorator' print 'call %s ' %func.__name__ return func(x, y) return f3 return f2 @f1('yinheyi') def sum(x,y): return x + y print sum(2,3) print 'the name of sum is \'%s\'' %sum.__name__輸出為:
my name is yinheyi
i am using decorator
call sum
5
the name of sum is 'sum'
偏函式:functools.partial
幫助我們建立一個偏函式。它的作用為:把一個函式的某些引數給固定住(也就是設定預設值),返回一個新的函式,呼叫這個新函式會更簡單。
舉例說明,如int()函式,它可以把字串轉換為整數,加外,它還提供了額外的base引數,如果傳入
base
引數,就可以做N進位制的轉換。如:int('12345', base=8) 5349當我們想假設要轉換大量的二進位制字串,每次都傳入
int(x, base=2)
非常麻煩,於是,我們想到,可以定義一個int2()
的函式,預設把base=2
傳進去:def int2(x, base=2): return int(x, base)
functools.partial
就是幫助我們建立一個偏函式的,不需要我們自己定義int2()
,可以直接使用下面的程式碼建立一個新的函式int2
:>>> import functools >>> int2 = functools.partial(int, base=2) >>> int2('1000000') 64 >>> int2('1010101') 85所以,簡單總結
functools.partial
的作用就是,把一個函式的某些引數給固定住(也就是設定預設值),返回一個新的函式,呼叫這個新函式會更簡單。注意到上面的新的
int2
函式,僅僅是把base
引數重新設定預設值為2
,但也可以在函式呼叫時傳入其他值:>>> int2('1000000', base=10) 1000000
模組:在Python中,一個.py檔案就稱之為一個模組(Module)。
為了避免模組名衝突,Python又引入了按目錄來組織模組的方法,稱為包(Package)。例如兩個名不hello.py的模組分別在china的包和school裡的包裡,然後呢,現在它們的名字分別為:china.hello與school.hello, 這樣就不衝突了吧。
每一個包目錄下面都會有一個
__init__.py
的檔案,這個檔案是必須存在的,否則,Python就把這個目錄當成普通目錄,而不是一個包。自己寫一個模組:(主要學習它的格式),建立一個hello.py的檔案,內容如下:
1 #!/usr/bin/python 2 # -*- coding: utf-8 -*- 3 4 'this is a hello module, i am coming ' 5 __author__='yinheyi' 6 7 import sys 8 9 def test(): 10 args = sys.argv 11 if len(args) == 1: 12 print 'hello,world' 13 print '你好,世界!' 14 elif len(args) == 2: 15 print 'hello,%s' % args[1] 16 else: 17 print '你的引數個數不對啊,我的哥!' 18 if __name__== '__main__': 19 test()
第2行註釋表示.py檔案本身使用標準UTF-8編碼;
第4行是一個字串,表示模組的文件註釋,任何模組程式碼的第一個字串都被視為模組的文件註釋;
第5行使用
__author__
變數把作者寫進去,這樣當你公開原始碼後別人就可以瞻仰你的大名;注意:
if __name__=='__main__': test()
當我們在命令列執行
hello
模組檔案時,Python直譯器把一個特殊變數__name__
置為__main__
,而如果在其他地方匯入該hello
模組時,則不會置為__main__, 所以我們可以直接執行這個模組哦,用於執行測試。給模組起一個別名:
import 模組名 as 別名
模組內的變數與函式的作用域:
在一個模組中,我們可能會定義很多函式和變數,但有的函式和變數我們希望給別人使用,有的函式和變數我們希望僅僅在模組內部使用。在Python中,是通過
_
字首來實現的。正常的函式和變數名是公開的(public),可以被直接引用,比如:
abc
,x123
,PI
等;類似
__xxx__
這樣的變數是特殊變數,可以被直接引用,但是有特殊用途,比如上面的__author__
,__name__
就是特殊變數,hello
模組定義的文件註釋也可以用特殊變數__doc__
訪問,我們自己的變數一般不要用這種變數名;
類中,__xxx
這樣的函式或變數就是非公開的(private),即有__開頭的名字;模組的搜尋路經:預設情況下,Python直譯器會搜尋當前目錄、所有已安裝的內建模組和第三方模組,搜尋路徑存放在
sys
模組的path
變數中。如果我們要新增搜尋目錄,有兩種方法,
一是直接修改sys.path,這種方法在退出python後,會失效的。
>>> import sys >>> sys.path.append('你自己的路經')
二是設定環境變數PYTHONPATH.可以在.bashrc裡新增的,如,export PYTHONPATH = ‘目錄‘:$PYTHONPATH
使用__future__模組:比如當我們是python2.7時,而我們想使用python3.4的python的功能時,怎麼辦呢?我們可以從
__future__模組裡,匯入我們想要用的功能。如除法:
#這是在python2.7中的 >>> 5/3 1 #匯入新的; >>> from __future__ import division >>> 5/3 1.6666666666666667
面向物件的程式設計:它就是把一個物件作為基本單元,這個物件裡有資料,也有對資料的操作方法啦。你看看C語言中,是不是以函式 為單元呢??這就是差別。例如一個水杯,它的元素就是水,它可以的操作有加水,倒水等。
面向物件程式設計的過程很簡單,首先建立一個類(其實,我認為就是一個數據型別啦,如int),然後再建立這個類的物件就可以啦。就好像你定義了一個汽車,然後,根據你的定義造出汽車的例項就可以啦。
類的定義,舉個例子:
#這是從 最根類繼承的,舊的方式定義Python類允許不從object類繼承,但這種程式設計方式已經嚴重不推薦使用。任何時 候,如果沒有合適的類可以繼承,就繼承自object類。
7 class Car(object): 8 #定義一個含有的屬性啦; 9 color_ = '' 10 weight_ = 0 11 __wheel_ = 4 #可以通過__開頭開定義私有的屬性; 12 #定義它的方法; 13 def __init__(self, color, weight, wheel): 14 self.color_ = color 15 self.weight_ = weight 16 self.__wheel_ = wheel 17 def get_color(self): 18 return self.color_ 19 def get_weight(self): 20 return self.weight_