python学习之路3之面向对象与继承

(一)面向对象

类:用来描述具有相同属性和方法的对象的集合

一. 类的命名方式

  1. 大驼峰 首字母大写
  2. 见名知意
  3. 区分大小写

类的实例:

class Women:
    sex = '女'
    faceValue = '高'
    height = '168'
    weight = '85斤'
    color = 'yellow'
    def makeMoney(self):
        print("可以赚钱")
    def cooking(self):
        print("做饭")
print(Women)  # <class '__main__.Women'>

二 . 对象

类的实例化为对象

object = 类名([参数])

实例:

lisi = Women()  # 将Women类实例化成对象
print(lisi)  # <__main__.Women object at 0x0000007524346A90>

三. 属性和方法的使用

object.属性名 # 调用属性

object.方法名() # 调用方法

注意:类里面的变量称之为属性 类里面的函数称之为方法

四. self的说明

方法里面的self代表的是当前类的实例化后的对象

self不是只能叫self, 别的也可以, 但是规范来说 都是用self

实例:

class A:
    name = ''
    def demo(self):
        print(self)  # self 代表当前实例化类的对象
        # print(id(self))
a = A()
a.demo()  # # <__main__.A object at 0x000000C22C4B8358>
print(a)  # <__main__.A object at 0x000000F74F008358>
b = A()
b.demo()  # <__main__.A object at 0x0000009EE9756860>
print(b)  # <__main__.A object at 0x000000EA38296860>

五. return - 方法的返回值

和函数一样 代码遇到return 下面就不在执行 会将值返回给调用处

没有return的方法 打印调用处的值为None 

实例:

class Demo:
    name = ''
    def speak(self):
    print("我是{}号类".format(self.name))
    def myReturn(self):
        return self.name
        # print(self.name)  # 不在执行
d2 = Demo()
# print(d2.name)  # ''
d2.name = 'd2'  # 给当前对象 添加对象属性 
d2.speak()  # 我是d2号类
print(d2.speak())  # None
d2Name = d2.myReturn()
print(d2Name)  # 返回值 d2

六. 对象属性和类属性

  1. 使用对象创建的属性称之为对象属性,对象属性只有在当前对象里才存在
  2. 如果使用对象属性创建了一个和类属性里面同名的属性,那么调用的时候会优先查找对象里面的属性
  3. 使用类里面的方法的参数self创建的属性也为对象属性
  4. 当使用对象.属性名 来改类里面的属性的时候,其实是在对象里面创建了一个同名的对象属性
  5. 当将对象里面的同名的属性删除掉以后,还是会调用类的属性(当对象属性存在时找对象属性,对象里不存在,找类属性)
  6. 不能在对象里 删除类里面的属性 只有使用的权利
  7. 使用类操作过的属性 所有对象在调用类属性的时候 都是修改后的属性

实例:创建对象属性的方法:

# 法一:
class A:
pass
a = A()
a.name = 'xxx'  # 创建对象属性 对象名.属性名
# 法二:
class A:
    def createVal(self):
        self.name = 'oo'
a = A()  
a.createVal()  # 创建对象属性

创建类属性的方法:

# 类名.属性名
A.name = '张三'

七. 给对象绑定方法

(1) 给对象绑定方法

from types import MethodType

实例:

from types import MethodType
class A:
    pass
def func(self):  # 类外的函数
    print("xxxxxxxxxx")
a = A()  
a.func = MethodType(func, a)  # 用MethodType将方法绑定到类的对象  MethodType(方法名,对象名)
a.func()  # 调用
a.func = func #或者用这种方法
a.func(a)

(2) 给类绑定方法

def func(self):
    print('func')
# 类名.属性名(函数名) = 函数名
A.func = MethodType(func,A) 

注意:

  1. 给对象绑定属性或者方法 只有当前对象有
  2. 给类绑定属性或者方法 所有当前类的实例化的对象都会拥有

八. __slots__限制对象动态添加属性

如果我们想要限制class的属性怎么办?比如,只允许对Student实例添加nameage属性。

为了达到限制的目的,Python允许在定义class的时候,定义一个特殊的__slots__变量,来限制该class能添加的属性:

>>> class Student(object):
...     __slots__ = ('name', 'age') # 用tuple定义允许绑定的属性名称
...

然后,我们试试:

>>> s = Student() # 创建新的实例
>>> s.name = 'Michael' # 绑定属性'name'
>>> s.age = 25 # 绑定属性'age'
>>> s.score = 99 # 绑定属性'score'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'Student' object has no attribute 'score'

由于'score'没有被放到__slots__中,所以不能绑定score属性,试图绑定score将得到AttributeError的错误。

使用__slots__要注意,__slots__定义的属性仅对当前类起作用,对继承的子类是不起作用的:

>>> class GraduateStudent(Student):
...     pass
...
>>> g = GraduateStudent()
>>> g.score = 9999

除非在子类中也定义__slots__,这样,子类允许定义的属性就是自身的__slots__加上父类的__slots__

九. 私有属性和私有方法

(1) 类的私有属性以__两个下划线作为开头,不能在类外进行使用和访问,在类的里面使用self.__属性名

私有属性的访问:

在类的外部: 对象._类名__属性名 进行查找

在类的内部: 通过方法里面的变量self.__属性名 进行调用

注意:在类的内部只要使用self.__属性名 就会去找私有属性 也就是__类名__属性名

(2) 类的私有方法:以__作为开头 不能在类的外部进行使用和访问 在类的里面使用 self.__方法名

在类的公有方法里面 通过self.__方法名调用

 (二)继承

概念: 面向对象编程带来的最大的好处就是代码的重用 实现代码重用的操作就是类的继承

被继承的类被称为 父类(基类)或超类

继承的类称之为子类

所有的类都是继承自一个超类object

(1) 单一继承

class  类名(继承的父类):

   pass

实例:

class A:
    # 不管是本类还是子类 只要实例化 就会调用(如果子类重写了Init函数子类实例化对象会覆盖父类的init函数)
    def __init__(self,name,age,sex):
        # print("一旦实例化就会自动调用  ")
        self.name = name
        self.age = age
        self.sex = sex
    def speak(self):
        print('我现在{}岁了 我叫{},我的性别是{}'.format(self.age,self.name,self.sex))
# a = A('张三',19,'男')
# print(a.name) # 张三
#cla.speak()
class B(A):
    # grade = ''   
 def __init__(self):   
     print("我是子类的")       
 # A.__init__(self,'张三',19,'男')    
pass
# b = B() # 如果子类没有重写父类的init的方法,会自动调用父类的init的方法
# b.sex  # 如果没实现子类的构造方法 会报 error 找不到 没有对父类进行初始化
class C(A):
    grade = ''
    def __init__(self,name,age,sex,grade): 
       print("我是子类的init函数")
        self.grade = grade
        A.__init__(self,name,age,sex)
    def speak(self):
        A.speak(self)  # 调用父类的speak
        print("我今年{} 我叫{} 我的成绩是{}".format(self.age,self.name,self.grade))
c = C('张三',13,'男',69)
# print(c.name)  # 父类的张三
# print(c.__dict__)  #  {'grade': 69, 'name': '张三', 'age': 13, 'sex': '男'}
c.speak()

注意:

  1. 类的单一继承 子类会继承父类私有以外的全部属性和方法
  2. 如果在子类里存在和父类同名的属性和方法 叫做方法或属性的重写(也就是会覆盖掉),再次调用的时候回调用子类的方法或属性
  3. 在子类里调用父类的方法 通过 类名.方法名(self,[参数…]) self代表当前类的实例化对象
  4. super(当前类名,当前self).方法名 (如果是单一继承super方法不建议加参数)

(2) 多继承

class 类名(继承的父类1, 继承的父类2,[父类3..])

    pass

注意:

  1. 当类进行多继承的时候 注意父类的顺序 当父类存在同名的属性或者方法的时候,会从继承的父类从左到右依次查找,使用第一个父类的属性或者方法

调用父类的方法:

class A:
    def speak(self):
        print("我是A类的speak方法")
    def a(self):
        print('a')
class B:
    def speak(self):
        print("我是B类的speak方")
    def b(self):
        print('b')
class C(A, B):   
    def speak(self):
        # super().speak()  # 还是从左往右找 我是A类的speak方法
        # super(C,self).speak()  # 传入当前类名 从左往右找  我是A类的speak方法
        super(A,self).speak()  # 找A后面的B  我是B类的speak方
        # super(B,self).speak()  # 找B后面 没有 报错
c = C()
c.speak()
# c.a()
# c.b()

二. 常用的属性

  1. __doc__ 类的说明
  2. __name__ 返回类名
  3. __base__ 返回一个父类
  4. __bases__ 返回多个父类
  5. __dict__ 以字典的形式返回对象或者类的信息

三. 静态方法(不用传self的方法)

@statimethod 

可以在类的实例化成对象来调用 也可以使用类名来调用

实例:

class A:
    @staticmethod
    def demo():  # 静态方法  
      print("类来调用")
a = A()
# a.demo()  #  如果没加staticmethod ,会报TypeError,没给方法写上self参数,
A.demo()  # ok
a.demo()  # 加上staticmethod 之后 ok

四. 魔术方法

  1. __init__ 构造方法 作为类的初始化
  2. __del__ 析构方法 在当前文件执行完毕之前去执行 或者有时候用del 对象名 触发
  3. __str__ 用于转换为人能够阅读的形式 
  4. __repr__ 转换为解释器查看的形式
  5. __add__ 运算符重载
  6. __getattr__ 调用不存在的属性的时候会触发
  7. __len__ 返回集合中所含元素的数量
  8. __getitem__ 返回与所给键对应的值
  9. __setitem__ 按一定的方式存储和key相关的value

猜你喜欢

转载自blog.csdn.net/zuggs_/article/details/81561022