Python面向对象基础
面向对象三个主要的特性是封装、抽象和继承;所谓封装,通俗的理解就是打包、集合,把一些零碎的命令封成一个工具,以后再用的时候,可以直接使用这个做好的工具而无需再去组装,一方面节省工作量,另一方面也不需再次测试工具的正确性;而抽象就是简化,简化到只剩下总体结构。一本书的目录,就是这本书的抽象,每个目录下对应的内容,是具体的实现;继承,是不劳而获的优越技能,继承而来,如同继承祖辈的财产,在面向对象编程中,继承是类继承其父类(或称基类)的财产,即方法,属性;从继承这一特性可以引出多态的特性,多态,多种形态,适应多种形态,如一个方法,能够对应多种要求的使用(方法重载)就是一种多态。
python支持多重继承,派生类可以重写父类所有的方法;原生python没有抽象类和接口的概念,不过可以借助第三方库abc.py实现抽象接口的功能。
python类
- class定义语法
# coding=utf-8
class MyClass:
"""
this is a sample class
"""
def __init__(self):
# this method just like a constructor
self.number = 100
self.x = "x"
self.y = "y"
print("this is init method")
# class variable
name = "myClass"
def func(self):
self.name = "func"
self.number = 200
#使用this替换self
def func2(this):
print(this.number)
def func3(self):
self.staticfunc()
self.classfunc()
self.func()
#class方法
@classmethod
def classfunc(cls):
print("classmethod")
#静态方法
@staticmethod
def staticfunc():
MyClass.classfunc()
print("staticmethod")
- 定义一个类使用
class <className>(baseclass)
; - __init__()方法是python类的constructor方法,在创建类的实例对象时会调用此方法;
- 上面的name变量是类变量,是此类的所有实例对象所共享的变量,即大家都可以读写这个name变量;
- 在方法内部定义的self.xx变量,是实例变量(属性),是由各个实例对象所拥有的属性,其他对象无法干涉;
- 关于方法定义时,第一个self参数,这个是固定的,是在实例对象调用方法时,隐式地将对象自身传给方法内部,所以才有self.xx的引用属性的方式,和java的this差不多,这里也可以把self改成this,只是默认这个名字叫self而已。
- @classmethod注解的方法,是类方法,可以由类名.方法名的方式调用,和java的静态方法类似
- @staticmethod注解的是静态方法,和类方法很相似,在使用上除了类方法隐式传递了类对象,似乎没有多大区分。
- 实例化
obj = MyClass()
obj.func()
obj.classfunc() # 实例对象和类都可以直接调用类方法和静态方法,反过来则不行
obj.staticfunc()
MyClass.classfunc()
MyClass.staticfunc()
obj.func3()
- 动态属性
class MyPlainClass:
pass
plainobj = MyPlainClass()
#动态添加
plainobj.name = "newname"
plainobj.address= "ch"
print(plainobj.name)
print(plainobj.address)
# output
"""
newname
ch
"""
# 动态删除
del plainobj.address
print(plainobj.address)
# output
"""
newname
Traceback (most recent call last):
File "F:/source/pyproject/TestClass.py", line 2, in <module>
class MyClass:
File "F:/source/pyproject/TestClass.py", line 42, in MyClass
print(plainobj.address)
AttributeError: 'MyPlainClass' object has no attribute 'address'
"""
- 继承
class MyChild(MyClass):
def func(self):
self.name = "mychild"
print("in mychild func")
@staticmethod
def staticfunc():
print("in mychild staticfunc")
def testInheritance():
pa = MyClass()
child = MyChild()
pa.func()
child.func()
pa.staticfunc()
child.staticfunc()
if __name__ == '__main__':
testInheritance()
# output:
"""
this is init method
this is init method
in mychild func
classmethod
staticmethod
in mychild staticfunc
"""
- 子类方法的查找规则,是自内而外的,和方法内的变量find规则一致,如果子类自己定义了或者重写了,就直接使用自己的,如果没有则去父类找,如__init__()方法
- 变量访问控制
class MyClass2:
# private class variable 只有类对象自己能访问,连子类对象也不能访问到这个数据
__name = "name"
# protected class variable 只有类对象和子类对象自己能访问到这些变量;
_protectname = "pttname"
# normal class variable
addr = "where"
#__object__ # special, python system use, user should not define like it
# access private/ protected and normal variable in function
def __init__(self):
self.__name = "init_name"
self._protectname = "init_protected_name"
self.addr = "init_addr"
self.__objname = "init_private_obj_name"
def get(self):
print(self.__name)
print(self._protectname)
print(self.addr)
print(self.__objname)
def testprivate():
pri = MyClass2()
pri.get()
print(pri._protectname)
"""
init_name
init_protected_name
init_addr
init_private_obj_name
init_protected_name
"""
pri.__objname # -->AttributeError: 'MyClass2' object has no attribute '__objname'
pri.__name #--> AttributeError: 'MyClass2' object has no attribute '__name'
print(pri._protectname)
pri._protectname = "what"
print(pri._protectname)
"""
init_protected_name
what
"""
双下划线定义的变量是私有变量,仅仅本类内部可以访问,和java一样,实例对象也不能直接使用obj.attribute的方式来访问属性;对私有变量的访问,可以使用类似java的pojo的方式访问。
单下划线定义的是保护变量,原则上不允许直接访问,但外部还是可以访问到这个变量,只是一个约定。
protected变量,推荐使用访问器访问。
@property
def protectname(self):
return self._protectname
The end.