欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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的东西似的,随着类的创建而创建而不是随着对象的创建而创建
相关标签: python