G
N
I
D
A
O
L

Python类和对象学习小记

由于某人的需求(?),我开始学起了Python的面向对象编程。因为以前学习过 C++ 的类和对象,接下来我尽可能从 C++ 的类和对象语法角度来快速过这部分内容。重载和多态这部分内容应该用不到,就没看了。

例程出处可见 Python 面向对象 | 菜鸟教程

例子1:基本知识

#!/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
  • 接下来的例子很有意思了,因为Python中可以在任意地方任意添加属性(成员变量),但是C++不能:
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'

例子2:内置属性

接下来的例子确实很有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__ : 类的文档字符串

例子3:对象销毁

这个例子涉及对象的销毁。

#!/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++中的析构函数
  • 对象的id可以简单理解为对象的“地址”

例子4:类的继承

以下几部分内容与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
  • 实例化子类,只会调用子类的构造方法(对应C++构造函数)
  • 如果在子类中需要父类的构造方法就需要显式的调用父类的构造方法,或者不重写父类的构造方法(意思就是子类不写构造函数就完事了)

重要注意!如果要继承父类的构造方法,可以使用 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

例子5:访问权限

#!/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)的变量, 只能是允许这个类本身进行访问了。

好了,就看到这吧。

---EOF---
posted @ 2022-05-26 13:19  漫舞八月(Mount256)  阅读(29)  评论(0编辑  收藏  举报