#前言
面向对象的编程离不开类,通过对类进行实例化,创建出了对象,关于PYTHON类也存在一些知识点或难点需要重点学习和讨论,本文主要从以下几个方面进行讨论:
class Person:
count = 0
def __init__(self,name):
self.name = name
def work(self):
print "work work"
有了类之后,就可以通过类创建对象了,类的基本特性:封装、继承、和多态。
封装比较好理解,把属性和方法封装在类中,通过类来描述具体事物。
继承,通过类创建的对象,就拥有了类的属性和方法,也可以通过类派生出子类,子类可以继承父类的属性和方法。
多态的概念不太容易说清楚,这个放在下面再讨论。
#属性的种类和作用域问题
属性分为:
class Person:
count = 0
def __init__(self,name):
self.name = name
def increase(self):
Person.count += 1
def work(self):
print "work work"
操作如下:
p1 = Persion("zhangsan")
p1.increase()
p2 = Persion("lisi")
p2.increase()
print Persion.count
print p1.count
可见,可以被类和实例访问,如果执行
p1.count = 10
print p1.count
print Person.count
可见类的count被p1的count屏蔽了
##实例属性
实例属性比较简单了,就是在实例中使用,Person类的name就是实例属性,通常在构造函数中用self.XXX来声明
##私有
#方法的种类和区别
这里说的方法指的是在类中定义的方法,包括:
>>> class Person:
... def aaa():
... print "a"
...
>>> Person.aaa()
Traceback (most recent call last):
File "", line 1, in
TypeError: unbound method aaa() must be called with Person instance as first argument (got nothing instead)
>>> p = Person()
>>> p.aaa()
Traceback (most recent call last):
File "", line 1, in
TypeError: aaa() takes no arguments (1 given)
##类方法
用@classmethod装饰的方法是类方法,例如
class Person:
count = 0
@classmethod
def cmeth(cls):
print cls.count
等同于:
class Person:
count = 0
def cmeth(cls):
print cls.count
cmeth = classmethod(cmeth)
##静态方法
用@staticmethod装饰的方法是静态方法,参数里为空,不用写东西,例如:
class Person:
… @staticmethod
… def smeth():
… print “static method”
这有啥用?我觉得似乎就是定义在类中的函数,似乎用函数也可以替代它的功能。
##这三种方法对比
主要区别在于参数。实例方法隐含的参数为类实例self,而类方法隐含的参数为类本身cls。
静态方法无隐含参数
##构造函数
用 init() 来做
就不多说了
#继承和重写的问题
继承,看下面例子:
class Person:
def __init__(self,name):
self.name = name
class Student(Person):
pass
class Teacher(Person):
def __init__(self,age):
self.age = age
s = Student("zhangsan")
print s.name
t = Teacher(30)
print t.name
输出s.name,可见学生类继承了父类的name属性,但是Teacher由于重新写构造函数,导致丢失了name属性,这就引发了错误
继承父类构造函数的写法
所以如果需要重写构造函数,则需要继承父类构造函数,否则父类中的实例属性不被继承可能会出错,写法如下:
第一种方法:
class Teacher(Person):
def __init__(self,name,age):
Person.__init__(self,name)
self.age = age
t = Teacher("lisi",30)
print t.name
显式调用父类构造函数,可以解决问题,或者使用第二种方法,用super
class Person:
def __init__(self,name):
self.name = name
class Teacher(Person):
def __init__(self,name,age):
super(Teacher,self).__init__(name)
self.age = age
t = Teacher("lisi",30)
print t.name
用super后发现报错,
Traceback (most recent call last):
File "/Users/wz/class_python.py", line 10, in
t = Teacher("lisi",30)
File "/Users/wz/class_python.py", line 7, in __init__
super(Teacher,self).__init__(name)
TypeError: super() argument 1 must be type, not classobj
这里需要注意,使用super,父类必须有继承的类,如果没有就用object
修改为:
class Person(object):
def __init__(self,name):
self.name = name
这样就ok了,两种方法的区别?
建议使用super,在处理多继承时候会更加智能一点。
#再谈多态
继承和封装都比较容易理解,那么多态应该怎么理解?
多态从字面意思看,就是多种形态,我觉得多态可能体现在多个方面,
例如,person类继承出student和teacher,这是不是也算person的多种形态,属于多态的范畴吧
比如方法重新后,又是多种形态
又如list dict都有len函数,算不算多态?
使用+可以运算多种类型,是不是属于运算符都多态?
所以,我觉得多态可能体现在方方面面,有了类和继承,自然就出现类多态
#多继承
指的是一个子类继承多个父类,这个在java种我记得似乎是不允许的,不过java种可以实现多个接口
这里要注意,先继承的父类的方法优先生效
关于类中需要注意的知识点先写这么多,感觉有可能没有总结全,等想到了再补充吧
#参考:
关于Python类属性与实例属性的讨论 http://python.jobbole.com/85100/
python super用法:
https://www.cnblogs.com/wjx1/p/5084980.html
https://www.cnblogs.com/lijunjiang2015/p/7802410.html 私有