Python 3语法小记(八)类class

Python 3 中只有新式类,没有旧式类,不需要显示的指定,你定义的类都是新式类

如果你不知道新式类和旧式类的区别,那么,也不用知道了


定义:

>>> class Nothing:
	#定义方法和属性
	pass

>>>


类里面用 def 定义方法,它不叫函数,因为每一个方法的第一个参数都是 self,但在调用时我们不必提供,程序会自动将第一个参数绑定到所属的实例上

>>> class Hello:
	def greet(self,name):
		print ("Hello,"+name)

		
>>> me = Hello() #要加()不然,不是实例
>>> me.greet('Cheng') #只需第一个参数
Hello,Cheng


Python 中默认情况下的方法和特性都是公有的,如果你想变为私有的,那么要在方法和特性的名字前加上双下划线 __ 

>>> class Some:
	name = "Jane"

	
>>> she = Some()
>>> she.name #这里可以访问
'Jane'
>>> class Some:
	 __name = "Jane"

	
>>> she = Some()
>>> she.name  #这里不可以
Traceback (most recent call last):
  File "<pyshell#48>", line 1, in <module>
    she.name
AttributeError: 'Some' object has no attribute 'name'
>>> she._Some__name #通过 _类名__方法或特性名,我们又可以访问它
'Jane'
>>> class C:
	def __test(self):
		print('in C...')
	def call(self):
		self.__test() #类内访问私有方法和特性

		
>>> c = C()
>>> c.call()
in C...

所以,你不可能完全限制其他人无法访问到你的类中方法和特性,所以,Python 并不能实现完全的封装


继承:
将其他类名写在class语句后的圆括号内就表示继承于某类
class 类名(基类名)
   语句块

>>> class A:
	def printA(self):
		print("in A...")

		
>>> class B(A):
	def printB(self):
		print('in B...')

		
>>> issubclass(A,B) #A不是B的子类
False
>>> issubclass(B,A) #B是A的子类
True
>>> B.__bases__  #B的基类
(<class '__main__.A'>,)
>>> b = B()
>>> isinstance(b,B)  #询问b是否是B的实例
True
>>> b.printA() #访问A中的方法
in A...

多继承:
多继承的方法很容易,把几个类名写在一起就行了


class 类名(基类名1,基类名2,基类名3)
   语句块

子类中同名的方法会覆盖基类的方法,方法的调用跟继承的顺序有关,即方法在子类中未找到时,从左到右查找父类中是否包含方法

看下面的例子:

>>> class A:
	def test(self):
		print("in A...")

		
>>> class B(A):
	def test(self):
		print('in B...')

		
>>> class C(A):
	def test(self):
		print('in C...')

		
>>> class D(B,C):
	def test(self):
		print('in D...')

		
>>> d = D()
>>> d.test() #如果子类拥有该方法,那直接调用该方法
in D...
>>> class D(B,C): #重定义类D
	pass

>>> d = D()
>>> d.test() #B先继承,在B中首先找到该方法,调用B的方法
in B...
>>> class D(C,B): #再次重定义,改变了继承顺序
	pass

>>> d = D()
>>> d.test() #这次调用了C的方法
in C...
>>> 

当然,如果D、B、C都没有该方法,而A有,那么自然是调用A的方法


>>> hasattr(d,'test') #对象d是否有test方法
True
>>> hasattr(d,'next') #对象d是否有next方法
False
>>> hasattr(d.test,'__call__') #询问d的test方法是否可调用
True


Python类的“构造函数” __init()__

将类实例化时,会创建一个空的类实例,一般的 Python 类的定义中会有一个特殊的方法来初始化,这个方法就是__init__(),当调用了类的实例化方法后,__init__()方法会立刻被这个类的实例调用。所以,__init__()不是构造函数,而是一个普通的方法.

>>> class A:
	count = 0;
	def __init__(self):
		A.count += 1  #每次调用该方法 count 自增 1
	def output(self):
		print(self.count)

		
>>> a1 = A() 
>>> a1.output()
1
>>> a2 = A() 
>>> a2.output()
2
>>> class A:
	def __init__(self,name):
		self.name = name

		
>>> a = A('Jane')


Python 还有一个类似于“析构函数”的方法 __del__,但不建议使用,Python 的内存管理是用引用计数的,但引用数为0时销毁对象,但你很难确定什么时候 Python 会调用 del 方法,所以避免莫名其妙的错误的最好方法是不要使用它,将所有你要del做的事情写在一个主动调用的方法,然后自己进行管理

再说说Python的类属性和实例属性

类属性是属于一个类的变量,就像是C++中类的静态成员变量,你只需将该属性定义在所有方法的作用域外,即为类属性,但一般是紧跟在类名后面,类属性为所有实例所共有,你可以通过 类名.属性 来调用类属性
>>> class A:
	count = 0; #这就是类属性
	def __init__(self):
		A.count += 1  #每次调用该方法 count 自增 1
	def output(self):
		print(self.count)

>>> a1 = A()
>>> a1.output()
1
>>> A.count = 0
>>> A.count
0
>>> a1.output()
0


实例属性是属于实例自己的属性,你可以在任何方法中添加新的实例属性,甚至在类外添加,Python会在实例属性初次使用时,创建该属性并赋值

>>> class A:
	def __init__(self):
		self.num = 1  #添加实例属性num
	def again(self,name):
		self.name = name #添加实例属性name

		
>>> a1 = A()
>>> a1.num
1
>>> a1.name #这时实例 a1 中还没有实例属性 name
Traceback (most recent call last):
  File "<pyshell#38>", line 1, in <module>
    a1.name #这时实例 a1 中还没有实例属性 name
AttributeError: 'A' object has no attribute 'name'
>>> a1.again('Jane')
>>> a1.name #现在有了...
'Jane'
>>> a1.call = '123456' #添加a1的实例属性 call
>>> a1.call
'123456'


继续看下面的例子:

>>> class A:
	count = 0
	def __init__(self):
		A.count += 1
	def output(self):
		print(self.count)

		
>>> a1 = A()
>>> a2 = A()
>>> a3 = A()
>>> A.count # A的类属性count这时为3
3
>>> A.count = 2 #更改A的类属性为2
>>> a1.count,a2.count, a3.count, A.count #A的所有实例的count也同样改变
(2, 2, 2, 2)
>>> a1.count = 5 #通过A的一个实例a1更改count
>>> a1.count, a2.count, a3.count, A.count #只有a1的count发生改变
(5, 2, 2, 2)
>>> A.count = 4 #再次更改A的类属性为4
>>> a1.count, a2.count, a3.count, A.count  #这时a1的count还是保持为5
(5, 4, 4, 4)  

通过上面的例子我们可以看到,类属性为所有实例和类所共有,通过 类名.类属性 可以更改类属性,并且所有实例的类属性也随之改变,但通过 实例名.类属性 来改变类属性,该实例的该类属性会变为实例属性,而不影响其他实例的类属性,以后通过 类名.类属性 来更改类属性,也不会影响到该实例的这个属性了,因为它变为实例属性啦。(好吧,我承认有点晕o(╯□╰)o)






  • 12
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值