Python入门学习(面向对象)

2017-11-20  本文已影响17人  Stan_Z

版权声明:本文为作者原创,转载必须注明出处。

转载请注明出处:http://www.jianshu.com/p/2f97ac0f2a42

一、创建类

class Student:
    name = "jack"#属性
    age = 18 #公有属性
    __private_sttrs = ""#两个下划线开头,声明该属性为私有

def __init__(self,age):#__init__是构造方法
    self.age = age
    print ("init")

def __private_method(self):#两个下划线开头,声明该方法为私有方法,不能在类地外部调用。在类的内部调用
    print "private method"

def setName(self,name):#方法
   self.name = name
   print("setName")

stu = Student(20)#创建实例对象
stu.setName("jim")#调用方法

print stu.name
print stu.age

self 代表类的实例,self 在定义类的方法时是必须有的,虽然在调用时不必传入相应的参数。
self 不是 python 关键字,只是习惯用这个命名表示类的实例,我们把他换成 runoob 也是可以正常执行

class Test:
    def prt(self):
        print(self)
        print(self.__class__)


t = Test()
t.prt()

二、添加,删除,修改类的属性

stu.gender = "male" #类中没有gender属性,直接添加属性
stu.gender = "female"#修改属性
del stu.gender #删除属性

三、访问属性的函数方法
你也可以使用以下函数的方式来访问属性:
getattr(obj, name[, default]) : 访问对象的属性。
hasattr(obj,name) : 检查是否存在一个属性。
setattr(obj,name,value) : 设置一个属性。如果属性不存在,会创建一个新属性。
delattr(obj, name) : 删除属性。

hasattr(stu, "age")    # 如果存在 'age' 属性返回 True。
getattr(stu, "age")    # 返回 'age' 属性的值
setattr(stu, "age", 8) # 添加属性 'age' 值为 8
delattr(stu, "age")    # 删除属性 'age'

四、Python内置类属性
dict : 类的属性(包含一个字典,由类的数据属性组成)
doc :类的文档字符串
name: 类名
module: 类定义所在的模块(类的全名是'main.className',如果类位于一个导入模块mymod中,那么 className.module 等于 mymod)
bases : 类的所有父类构成元素(包含了一个由所有父类组成的元组)

print Student.__dict__
print Student.__doc__
print Student.__name__
print Student.__module__
print Student.__bases__
输出结果:
 {'__module__': '__main__', 'name': 'jack', 'setName': <function setName at 
 0x1096c37d0>, 'age': 18, '__doc__': None, '__init__': <function __init__ at 
 0x1096c3758>}
 None
 Student
 __main__
 ()

五、类的继承
面向对象的编程带来的主要好处之一是代码的重用,实现这种重用的方法之一是通过继承机制。继承完全可以理解成类之间的类型和子类型关系。
需要注意的地方:继承语法 class 派生类名(基类名)://... 基类名写在括号里,基本类是在类定义的时候,在元组之中指明的。
在python中继承中的一些特点:
1:在继承中基类的构造(init()方法)不会被自动调用,它需要在其派生类的构造中亲自专门调用。
2:在调用基类的方法时,需要加上基类的类名前缀,且需要带上self参数变量。区别在于类中调用普通函数时并不需要带上self参数
3:Python总是首先查找对应类型的方法,如果它不能在派生类中找到对应的方法,它才开始到基类中逐个查找。(先在本类中查找调用的方法,找不到才去基类中找)。
如果在继承元组中列了一个以上的类,那么它就被称作"多重继承" 。
语法:
派生类的声明,与他们的父类类似,继承的基类列表跟在类名之后,如下所示:

 class SubClassName (ParentClass1[, ParentClass2, ...]):
     'Optional class documentation string'
     class_suite

 class Parent:  # 定义父类
    parentAttr = 100

    def __init__(self):
        print "调用父类构造函数"

    def parentMethod(self):
        print '调用父类方法'

    def setAttr(self, attr):
        Parent.parentAttr = attr

    def getAttr(self):
        print "父类属性 :", Parent.parentAttr


 class Child(Parent):  # 定义子类
    def __init__(self):
       print "调用子类构造方法"

    def childMethod(self):
       print '调用子类方法'

c = Child()  # 实例化子类
c.childMethod()  # 调用子类的方法
c.parentMethod()  # 调用父类方法
c.setAttr(200)  # 再次调用父类的方法 - 设置属性值
c.getAttr()  # 再次调用父类的方法 - 获取属性值

六、多继承

class P1(object):
    def foo(self):
        print 'p1-foo'

class P2(object):
    def foo(self):
        print 'p2-foo'

def bar(self):
    print 'p2-bar'

class C1(P1, P2):
    pass

class C2(P1, P2):
     def bar(self):
         print 'C2-bar'

class D(C1, C2):
     pass

对经典类和新式类来说,属性的查找顺序是不同的。现在我们分别看一下经典类和新式类两种不同的表现
1、经典类

d = D()
d.foo() # 输出 p1-foo
d.bar() # 输出 p2-bar
实例d调用foo()
时,搜索顺序是
D = > C1 = > P1
实例d调用bar()
时,搜索顺序是
D = > C1 = > P1 = > P2
换句话说,经典类的搜索方式是按照“从左至右,深度优先”的方式去查找属性。d先查找自身是否有foo方法,没有则查找最近的父类C1里是否有该方法,如果没有则继续向上查找,直到在P1中找到该方法,查找结束。
2、新式类
使用新式类要去掉第一段代码中的注释

d = D()
d.foo() # 输出 p1-foo
d.bar() # 输出 c2-bar
实例d调用foo()
时,搜索顺序是
D = > C1 = > C2 = > P1
实例d调用bar()
时,搜索顺序是
D = > C1 = > C2
可以看出,新式类的搜索方式是采用“广度优先”的方式去查找属性。

可以调用类的mro属性来查看查找顺序

七、方法重写
class Parent: # 定义父类
def myMethod(self):
print '调用父类方法'

class Child(Parent):  # 定义子类
    def myMethod(self):
        print '调用子类方法'

c = Child()  # 子类实例
c.myMethod()  # 子类调用重写方法

单下划线、双下划线、头尾双下划线说明:
foo: 定义的是特殊方法,一般是系统定义名字 ,类似 init() 之类的。
_foo: 以单下划线开头的表示的是 protected 类型的变量,即保护类型只能允许其本身与子类进行访问,不能用于 from module import *
__foo: 双下划线的表示的是私有类型(private)的变量, 只能是允许这个类本身进行访问了。

上一篇下一篇

猜你喜欢

热点阅读