由于某人的需求(?),我开始学起了Python的面向对象编程。因为以前学习过 C++ 的类和对象,接下来我尽可能从 C++ 的类和对象语法角度来快速过这部分内容。重载和多态这部分内容应该用不到,就没看了。
例程出处可见 Python 面向对象 | 菜鸟教程。
目录#!/usr/bin/python # -*- coding: UTF-8 -*- class Employee: '所有员工的基类' empCount = 0 def __init__(self, name, salary): self.name = name self.salary = salary Employee.empCount += 1 def displayCount(self): print "Total Employee %d" % Employee.empCount def displayEmployee(self): print "Name : ", self.name, ", Salary: ", self.salary "创建 Employee 类的第一个对象" emp1 = Employee("Zara", 2000) "创建 Employee 类的第二个对象" emp2 = Employee("Manni", 5000) emp1.displayEmployee() emp2.displayEmployee() print "Total Employee %d" % Employee.empCount
class Employee: '所有员工的基类'
:类文档字符串,相当于注释,但不是真的注释,而是作为了代码的一部分,方便阅读代码empCount
:应视为C++的静态成员变量(对,是加修饰词 static 的那种,真的不是普通成员变量,普通成员变量都在“构造函数”中就已经“声明”了。注意,因为python的语法没那么严格,不需要声明变量,别问我为什么python是这个鬼样子)def __init__(self, name, salary)
:可视为构造函数def displayCount(self)
:类的方法,可视为成员函数self
:相当于C++中的 this 指针,实际上也可以换成别的名字。类的方法必须都加上这个参数,用于指代自己"创建 Employee 类的第一个对象" emp1 = Employee("Zara", 2000) "创建 Employee 类的第二个对象" emp2 = Employee("Manni", 5000)
emp1.displayEmployee() emp2.displayEmployee() print "Total Employee %d" % Employee.empCount
emp1.age = 7 # 添加一个 'age' 属性 emp1.age = 8 # 修改 'age' 属性 del emp1.age # 删除 'age' 属性
因此,需要引入一个访问属性的机制,以方便监控属性:
hasattr(emp1, 'age') # 如果存在 'age' 属性返回 True。 getattr(emp1, 'age') # 返回 'age' 属性的值 setattr(emp1, 'age', 8) # 添加属性 'age' 值为 8 delattr(emp1, 'age') # 删除属性 'age'
接下来的例子确实很有Python的味道。。。
#!/usr/bin/python # -*- coding: UTF-8 -*- class Employee: '所有员工的基类' empCount = 0 def __init__(self, name, salary): self.name = name self.salary = salary Employee.empCount += 1 def displayCount(self): print "Total Employee %d" % Employee.empCount def displayEmployee(self): print "Name : ", self.name, ", Salary: ", self.salary print "Employee.__doc__:", Employee.__doc__ print "Employee.__name__:", Employee.__name__ print "Employee.__module__:", Employee.__module__ print "Employee.__bases__:", Employee.__bases__ print "Employee.__dict__:", Employee.__dict__
Python的内置类属性:
__name__
: 类名__bases__
: 类的所有父类构成元素(包含了一个由所有父类组成的元组)。这个可以直接查看被继承的类有哪些,比C++方便多了__module__
: 类定义所在的模块(类的全名是'__main__.className',如果类位于一个导入模块mymod中,那么className.__module__ 等于 mymod)__doc__
: 类的文档字符串这个例子涉及对象的销毁。
#!/usr/bin/python # -*- coding: UTF-8 -*- class Point: def __init__( self, x=0, y=0): self.x = x self.y = y def __del__(self): class_name = self.__class__.__name__ print class_name, "销毁" pt1 = Point() pt2 = pt1 pt3 = pt1 print id(pt1), id(pt2), id(pt3) # 打印对象的id del pt1 del pt2 del pt3
输出结果:
3083401324 3083401324 3083401324 Point 销毁
def __del__(self)
:相当于C++中的析构函数以下几部分内容与C++的习惯大有不同,虽然核心是相同的。注意其区别。
#!/usr/bin/python # -*- coding: UTF-8 -*- 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() # 再次调用父类的方法 - 获取属性值
输出:
调用子类构造方法 调用子类方法 调用父类方法 父类属性 : 200
class C(A, B): # 继承类 A 和 B
重要注意!如果要继承父类的构造方法,可以使用 super 关键字:
super(子类,self).__init__(参数1,参数2,....) 或 父类名称.__init__(self,参数1,参数2,...)
例子:
class Father(object): def __init__(self, name): self.name=name print ( "name: %s" %( self.name)) def getName(self): return 'Father ' + self.name class Son(Father): def __init__(self, name): super(Son, self).__init__(name) print ("hi") self.name = name def getName(self): return 'Son '+self.name if __name__=='__main__': son=Son('runoob') print ( son.getName() )
输出(先调用父类方法,再调用子类方法):
name: runoob hi Son runoob
#!/usr/bin/python # -*- coding: UTF-8 -*- class JustCounter: __secretCount = 0 # 私有变量,加了两个下划线在开头 publicCount = 0 # 公开变量 def count(self): self.__secretCount += 1 self.publicCount += 1 print self.__secretCount counter = JustCounter() counter.count() counter.count() print counter.publicCount print counter.__secretCount # 报错,实例不能访问私有变量
__private_attrs:两个下划线开头加在属性名字开头,表示为私有属性 类内部使用:self.__private_attrs
__private_method:两个下划线开头加在方法名字开头,表示为私有方法 类的内部调用:self.__private_methods
__foo__: 定义的是特殊方法,一般是系统定义名字 ,类似 __init__() 之类的。
_foo: 以单下划线开头的表示的是 protected 类型的变量,即保护类型只能允许其本身与子类进行访问,不能用于 from module import * (保护属性在 C++ 中应该很熟悉了,父类子类都能访问,但是外部不能访问;私有属性是父类自己能访问,继承的子类和外部不能访问)
__foo: 双下划线的表示的是私有类型(private)的变量, 只能是允许这个类本身进行访问了。
好了,就看到这吧。