1 類(lèi)的定義
假設(shè)需要定義一個(gè)人
# person.py
class Person:
def __init__(self, age=18, code=3):
self.age, self.code = age, code
def total(self):
return self.age + self.code
上述是一個(gè)構(gòu)造函數(shù)国觉,如果在java里面我們這樣玩,會(huì)這樣寫(xiě):
public class Person{
private int age;
private int code;
public Person(age,code){
this.age = age;
this.code = code
}
getter,setter省略...
}
我們需要注意的是python這種連等方式探熔。
from person import *
p = Person(10, 10) # __init__ 被調(diào)用
type(p)
<class 'person.Person'>
p.age, p.code
(10, 10)
我們?cè)趐erson初始化的方法上寫(xiě)了昌阿,2個(gè)默認(rèn)值。
對(duì)一切皆對(duì)象的 Python 來(lái)說(shuō)言疗,類(lèi)自己當(dāng)然也是對(duì)象:
type(Person)
<class 'type'>
dir(Person)
['__class__', '__delattr__', '__dict__', ..., '__init__','total' ...]
Person.__class__
<class 'type'>
使用dir()函數(shù)可以查看對(duì)像內(nèi)所有屬于及方法晴圾,在python中任何東西都是對(duì)像,一種數(shù)據(jù)類(lèi)型噪奄,一個(gè)模塊等疑务,都有自己的屬性和方法,除了常用方法外梗醇,其它的你不需要全部記住它知允,交給dir()函數(shù)就好了。
查看列表都有哪些方法
dir([ ])
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__delslice__', '__doc__',
'__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__getslice__', '__gt__',
'__hash__', '__iadd__', '__imul__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__mul__',
'__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__',
'__setitem__', '__setslice__', '__sizeof__', '__str__', '__subclasshook__', 'append', 'count',
'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'sort']
很好叙谨,我們的到了列表所有的方法温鸽,熟悉的有append,insert等,具體不說(shuō)明了手负。好我們繼續(xù)看
class Person:
...
def set(self, x, y):
self.x, self.y = x, y
p = Person(10, 10)
p.set(0, 0)
p.x, p.y
(0, 0)
p.set(...) 其實(shí)只是一個(gè)語(yǔ)法糖涤垫,你也可以寫(xiě)成 Point.set(p, ...),這樣就能明顯看出 p 就是 self 參數(shù)了:
Point.set(p, 0, 0)
p.x, p.y
(0, 0)
上面這種寫(xiě)法竟终,是一樣的蝠猬。
訪(fǎng)問(wèn)控制
Python 沒(méi)有 public / protected / private 這樣的訪(fǎng)問(wèn)控制,如果你非要表示“私有”统捶,習(xí)慣是加雙下劃線(xiàn)前綴榆芦。
class Point:
def __init__(self, x=0, y=0):
self.__x, self.__y = x, y
def set(self, x, y):
self.__x, self.__y = x, y
def __f(self):
pass
__x、__y 和 __f 就相當(dāng)于私有了:
>>> p.__x
...
AttributeError: 'Point' object has no attribute '__x'
>>> p.__f()
...
AttributeError: 'Point' object has no attribute '__f'
嘗試打印 Point 實(shí)例:
>>> p = Point(10, 10)
>>> p
<point.Point object at 0x000000000272AA20>
可以看到我們打印出了這個(gè)p對(duì)象喘鸟,如果我們想換一種方式呢匆绣?
class Point:
def __repr__(self):
return 'Point({}, {})'.format(self.__x, self.__y)
>>> repr(p)
'Point(10, 10)'
我們?cè)谝粋€(gè)類(lèi)中自定義了一個(gè)repr方法,調(diào)用他什黑。下面我們來(lái)看一些野路子崎淳。。愕把。
裝飾器@staticmethod和@classmethod有什么區(qū)別?
class A(object):
def foo(self,x):
print "executing foo(%s,%s)"%(self,x)
@classmethod
def class_foo(cls,x):
print "executing class_foo(%s,%s)"%(cls,x)
@staticmethod
def static_foo(x):
print "executing static_foo(%s)"%x
a=A()
a.foo(1)
# executing foo(<__main__.A object at 0xb7dbef0c>,1)
a.class_foo(1)
# executing class_foo(<class '__main__.A'>,1) //注意傳遞的是cls
A.class_foo(1)
# executing class_foo(<class '__main__.A'>,1)
一個(gè)簡(jiǎn)單的例子很直接說(shuō)明了classmethod的用法
class Kls(object):
no_inst = 0
def __init__(self):
Kls.no_inst = Kls.no_inst + 1
@classmethod
def get_no_of_instance(cls_obj):
return cls_obj.no_inst
ik1 = Kls()
ik2 = Kls()
ik3 = Kls()
print ik1.get_no_of_instance()
print Kls.get_no_of_instance()
// output 3
2 類(lèi)的繼承
舉一個(gè)教科書(shū)中最常見(jiàn)的例子拣凹。Circle 和 Rectangle 繼承自 Shape,不同的圖形恨豁,面積(area)計(jì)算方式不同嚣镜。
# shape.py
class Shape:
def area(self):
return 0.0
class Circle(Shape):
def __init__(self, r=0.0):
self.r = r
def area(self):
return math.pi * self.r * self.r
class Rectangle(Shape):
def __init__(self, a, b):
self.a, self.b = a, b
def area(self):
return self.a * self.b
>>> from shape import *
>>> circle = Circle(3.0)
>>> circle.area()
28.274333882308138
>>> rectangle = Rectangle(2.0, 3.0)
>>> rectangle.area()
6.0
繼承的方式很簡(jiǎn)單,在類(lèi)名上加個(gè)括號(hào)就行圣絮。
如果 Circle 沒(méi)有定義自己的 area:
class Circle(Shape):
pass
>>> Shape.area is Circle.area
True
一旦 Circle 定義了自己的 area祈惶,從 Shape 繼承而來(lái)的那個(gè) area 就被重寫(xiě)(overwrite)了:
>>> from shape import *
>>> Shape.area is Circle.area
False
通過(guò)類(lèi)的字典更能明顯地看清這一點(diǎn):
>>> Shape.__dict__['area']
<function Shape.area at 0x0000000001FDB9D8>
>>> Circle.__dict__['area']
<function Circle.area at 0x0000000001FDBB70>
所以,子類(lèi)重寫(xiě)父類(lèi)的方法,其實(shí)只是把相同的屬性名綁定到了不同的函數(shù)對(duì)象捧请》采可見(jiàn) Python 是沒(méi)有覆寫(xiě)(override)的概念的。
甚至可以動(dòng)態(tài)的添加方法:
class Circle(Shape):
...
# def area(self):
# return math.pi * self.r * self.r
# 為 Circle 添加 area 方法疹蛉。
Circle.area = lambda self: math.pi * self.r * self.r
lambda表達(dá)式返回一個(gè)函數(shù)對(duì)象活箕。
這樣吧我們寫(xiě)一個(gè)完整的繼承代碼把
輸出
3 多態(tài)
如前所述,Python 沒(méi)有覆寫(xiě)(override)的概念可款。嚴(yán)格來(lái)講育韩,Python 并不支持「多態(tài)」。
#!/usr/bin/env Python
class Animal:
def __init__(self, name=""):
self.name = name
def talk(self):
pass
class Cat(Animal):
def talk(self):
print "Meow!"
class Dog(Animal):
def talk(self):
print "Woof!"
a = Animal()
a.talk()
c = Cat("Missy")
c.talk()
d = Dog("Rocky")
d.talk()
其實(shí)我沒(méi)有虎你闺鲸,python里的多態(tài)看起來(lái)確實(shí)很low筋讨。。摸恍。下面講一個(gè)知識(shí)點(diǎn)
#!/usr/bin/env Python
class ProtectMe:
def __init__(self):
self.me = "qiwsir"
self.__name = "kivi"
@property
def name(self):
return self.__name
if __name__ == "__main__":
p = ProtectMe()
print p.name
怎么樣知道如何訪(fǎng)問(wèn)私有屬性了把悉罕。。
最后給大家?guī)?lái)一波福利立镶,我這里只貼代碼了壁袄,大家細(xì)看
itertools庫(kù)
迭代器(生成器)在Python中是一種很常用也很好用的數(shù)據(jù)結(jié)構(gòu),比起列表(list)來(lái)說(shuō)媚媒,迭代器最大的優(yōu)勢(shì)就是延遲計(jì)算嗜逻,按需使用,從而提高開(kāi)發(fā)體驗(yàn)和運(yùn)行效率缭召,以至于在Python 3中map,filter等操作返回的不再是列表而是迭代器栈顷。
itertools.accumulate
>>> import itertools
>>> x = itertools.accumulate(range(10))
>>> print(list(x))
[0, 1, 3, 6, 10, 15, 21, 28, 36, 45]
原函數(shù)是這樣寫(xiě)的
def accumulate(iterable, func=operator.add):
'Return running totals'
# accumulate([1,2,3,4,5]) --> 1 3 6 10 15
# accumulate([1,2,3,4,5], operator.mul) --> 1 2 6 24 120
it = iter(iterable)
try:
total = next(it)
except StopIteration:
return
yield total
for element in it:
total = func(total, element)
yield total
data = [3, 4, 6, 2, 1, 9, 0, 7, 5, 8]
>>> list(accumulate(data, operator.mul)) # running product
[3, 12, 72, 144, 144, 1296, 0, 0, 0, 0]
itertools.chain
>>> x = itertools.chain(range(3), range(4), [3,2,1])
>>> print(list(x))
[0, 1, 2, 0, 1, 2, 3, 3, 2, 1]
itertools.combinations
求列表或生成器中指定數(shù)目的元素不重復(fù)的所有組合
>>> x = itertools.combinations(range(4), 3)
>>> print(list(x))
[(0, 1, 2), (0, 1, 3), (0, 2, 3), (1, 2, 3)]
itertools.compress
按照真值表篩選元素
>>> x = itertools.compress(range(5), (True, False, True, True, False))
>>> print(list(x))
[0, 2, 3]
itertools.islice
def islice(iterable, *args):
# islice('ABCDEFG', 2) --> A B
# islice('ABCDEFG', 2, 4) --> C D
# islice('ABCDEFG', 2, None) --> C D E F G
# islice('ABCDEFG', 0, None, 2) --> A C E G
s = slice(*args)
it = iter(range(s.start or 0, s.stop or sys.maxsize, s.step or 1))
try:
nexti = next(it)
except StopIteration:
return
for i, element in enumerate(iterable):
if i == nexti:
yield element
nexti = next(it)
itertools.count(start=0, step=1)
# count(10) --> 10 11 12 13 14 ...
# count(2.5, 0.5) -> 2.5 3.0 3.5 ...
n = start
while True:
yield n
n += step
>>> x = itertools.count(start=20, step=-1)
>>> print(list(itertools.islice(x, 0, 5, 2)))
[20, 18, 16, 14,12]
itertools.cycle
>>> x = itertools.cycle('ABC')
>>> print(list(itertools.islice(x, 0, 10, 1)))
['A', 'B', 'C', 'A', 'B', 'C', 'A', 'B', 'C', 'A']
itertools.filterfalse
>>> x = itertools.filterfalse(lambda e: e < 5, (1, 5, 3, 6, 9, 4))
>>> print(list(x))
[5, 6, 9]
itertools.groupby
>>> x = itertools.groupby(range(10), lambda x: x < 5 or x > 8)
>>> for condition, numbers in x:
... print(condition, list(numbers))
True [0, 1, 2, 3, 4]
False [5, 6, 7, 8]
True [9]
好了,今天的講解也到這里了恼琼,我得去寫(xiě)代碼了妨蛹。。晴竞。