Python 包和模块、面向对象编程

模块

  • 区分包和目录:包的每一级都要有__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的东西似的,随着类的创建而创建而不是随着对象的创建而创建

你可能感兴趣的:(python)