Python 包和模块、面向对象编程
程序员文章站
2022-07-09 23:38:10
...
模块
- 区分包和目录:包的每一级都要有
__init__.py
- 当新版本的一个特性与旧版本不兼容时,该特性将会在旧版本中添加到
__future__
中,以便旧的代码能在旧版本中测试新特性。# python2中/是整除,python3中//是整除,/是除法但得到浮点数 >>> from __future__ import division >>> print 10 / 3 3.3333333333333335
Python面向对象编程
- 由于Python是动态语言,对每一个实例,都可以直接给他们的属性赋值
class Person(object): pass def cmp(x,y): if x < y : return -1 elif x > y : return 1 else : return 0 p1 = Person() p1.name = 'Bart' # 可以直接给实例添加属性,不同实例的属性可以不同 p2 = Person() p2.name = 'Adam' p3 = Person() p3.name = 'Lisa' L1 = [p1, p2, p3] L2 = sorted(L1,key=lambda x:x.name) print L2[0].name print L2[1].name print L2[2].name
- 在定义类时,可以为类添加一个特殊的
__init__()
方法,当创建实例时,init()方法被自动调用. -
__init__()
方法的第一个参数必须是 self(也可以用别的名字,但建议使用习惯用法),后续参数则可以*指定,和定义函数没有任何区别。 - __init__方法,除了接受 name、gender 和 birth 外,还可接受任意关键字参数
class Person(object):
def __init__(self,name,gender,birth,**kw):
self.name = name
self.gender = gender
self.birth = birth
for k , v in kw.iteritems():
setattr(self,k,v)
xiaoming = Person('Xiao Ming', 'Male', '1990-1-1', job='Student')
print xiaoming.name
print xiaoming.job
-
Python对属性权限的控制是通过属性名来实现的,如果一个属性由双下划线开头
__
,该属性就无法被外部访问 -
如果一个属性以
__xxx__
的形式定义,那它又可以被外部访问了,以__xxx__
定义的属性在Python的类中被称为特殊属性,有很多预定义的特殊属性可以使用 -
类属性
- 实例属性每个实例各自拥有,互相独立,而类属性有且只有一份。
class Person(object): address = 'Earth' def __init__(self, name): self.name = name
- 类属性是直接绑定在类上的,所以,访问类属性不需要创建实例,就可以直接访问
class Person(object): count = 0 def __init__(self,name): Person.count += 1 self.name = name p1 = Person('Bob') print(Person.count) p2 = Person('Alice') print(Person.count) p3 = Person('Tim') print(Person.count)
- 由于Python是动态语言,类属性也是可以动态添加和修改的
- 当实例属性和类属性重名时,实例属性优先级高,它将屏蔽掉对类属性的访问。
class Person(object): address = 'Earth' def __init__(self, name): self.name = name p1 = Person('Bob') p2 = Person('Alice') print 'Person.address = ' + Person.address p1.address = 'China' # 试图在实例变量中修改类属性 print 'p1.address = ' + p1.address print 'Person.address = ' + Person.address print 'p2.address = ' + p2.address 输出: Person.address = Earth p1.address = China # Ⅰ Person.address = Earth p2.address = Earth # Ⅱ
- I和Ⅱ表明在实例中修改类属性并没有改变 Person 的 address,而是给 p1这个实例绑定了实例属性address
-
Python中方法也是属性
- 因为方法也是一个属性,所以,它也可以动态地添加到实例上,只是需要用
types.MethodType()
把一个函数变为一个方法:
- 因为方法也是一个属性,所以,它也可以动态地添加到实例上,只是需要用
# 给一个实例动态添加方法并不常见,直接在class中定义要更直观。
import types
def fn_get_grade(self):
if self.score >= 80:
return 'A'
if self.score >= 60:
return 'B'
return 'C'
class Person(object):
def __init__(self, name, score):
self.name = name
self.score = score
p1 = Person('Bob', 90)
p1.get_grade = types.MethodType(fn_get_grade, p1, Person)
print p1.get_grade()
# => A
p2 = Person('Alice', 65)
print p2.get_grade()
# ERROR: AttributeError: 'Person' object has no attribute 'get_grade'
# 因为p2实例并没有绑定get_grade
# get_grade:是函数而不是方法(直接把 lambda 函数赋值给 self.get_grade 和绑定方法有所不同,函数调用不需要传入 self,但是方法调用需要传入 self)
class Person(object):
def __init__(self, name, score):
self.name = name
self.score = score
self.get_grade = lambda: 'A'
p1 = Person('Bob', 90)
print p1.get_grade
print p1.get_grade()
-
Python中的类方法
- 和属性类似,方法也分实例方法和类方法。
- 实例方法第一个参数 self 是实例本身。
- 定义类方法用
@classmethod
class Person(object): __count = 0 # 私有属性 # 通过标记一个 @classmethod,该方法将绑定到 Person 类上,而非类的实例。类方法的第一个参数将传入类本身,通常将参数名命名为 cls,上面的 cls.__count 实际上相当于 Person.__count。 @classmethod def how_many(cls): return cls.__count def __init__(self,name): self.name = name Person.__count += 1 print Person.how_many() p1 = Person('Bob') print Person.how_many() # 因为是在类上调用,而非实例上调用,因此类方法无法获得任何实例变量,只能获得类的引用(Person.how_many)。
- 类方法不需要创建实例,不需要new一个对象来调用,节省了创建实例的内存空间,就像static的东西似的,随着类的创建而创建而不是随着对象的创建而创建。
下一篇: 怎样让您的企业网站获得更多的流量和收益