初入Python 面向对象~~~~学习记录

学习记录~~~部分(学习ing~)

一、类的定义与创建:

定义:类(抽象的概念): 拥有着相同的特征(属性)和行为(方法)。

- 简单创建:

简单创建:

  • 类名的命名规则:大驼峰写法(每个单词的首字母大写)

  • class关键字创建

类的简单创建,

 class DogCat(object):  # 类名的命名规则:大驼峰写法(每个单词的首字母大写)
    pass

- 类属性:

类属性:

  • 类属性的赋予
 class Student(object):
    # 类属性
    class_name = "8班"  
    student_num = 30

这里创建了一个学生类后,又赋予了班级名和学生人数这个两个属性。而他们就是类属性。

  • 类属性的访问
 class Student(object):
    # 类属性
    class_name = "8班"
    student_num = 30

# 方法一   # 直接通过: 类名.类属性
print(Student.student_num)

# 方法二   # 先实例化对象,通过:实例对象.属性 来查找
s = Student()
print(s.student_num)

在上面代码中的方式二:它先实例化对象,通过:实例对象.属性 来查找,但是实例化对象的空间里没有student_num 这个属性,它就会继续在类空间里去找(或者去它继承的类里找)。

  • 类属性的修改
class Student(object):
    # 类属性
    class_name = "8班"
    student_num = 30
    name = "土狗"


# 类属性的修改 : 类名.属性名  ,如果没该属性就新建属性;如有,就修改它
Student.name = "憨猫"  # 修改
Student.age = 100  # 新建

print(Student.name)
print(Student.age)

直观结果:
初入Python 面向对象~~~~学习记录

二、实例对象

定义的类只有进行实例化,也就是使用该类创建对象之后,才可以利用。

- 实例对象方法: 类名()

 class Student(object):
    # 类属性
    class_name = "8班"
    student_num = 30
 
s = Student() # 实例化对象

- 实例对象方法: _ _ init _ _ 方法

当我们需要多个实例对象的时候,第一种方法就会造成代码的冗余,因此就有了__init__方法的作用了。
来个例子看看:

class Student(object):
    # 类属性
    name = "华子"

    # 方法
    def __init__(self, name, age):  # 形参,接收实参的传入
        self.name = name  # 对于这里的参数,前面的name是我们可以再自定义的,而后面的name是不可以变的,因为它要与我们的新参保持一致,就相当于函数里的传参
        self.age = age

    def eat(self):
        print('华子在吃饭')


s1 = Student('土狗', '18')  # 实参 ,参数的多少都可以自定义
s2 = Student('憨猫', '19')
s3 = Student('猪猪侠', '20')

print(s1.name)
print(s2.name)
print(s3.name)

print(s1.age)

看看运行结果:
初入Python 面向对象~~~~学习记录
这里注意的是,Student()实例化后才会赋值给 s1 等变量,而Student()实例化的时候它会自动的触发__init__方法,而我们又可以认为self就是s1,因为下图:
初入Python 面向对象~~~~学习记录
这里打印出了self和s1的id值,发现他们是相同的~~~所以,self就是s1,而self.属性名就是s1.属性名,self.属性名就是在向 s1 这个实例空间里创建实例属性。再就是这里的实参与形参的传入与接收,它是和函数的实参与形参相似的。

- 实例对象的属性赋予:实例对象.属性名

class Student(object):
    # 类属性
    class_name = "8班"
    student_num = 30
    name = "土狗"


s = Student()
s.name = '华仔'
s.age = 18

print(s.name)  # 查找name属性时,发现类空间和实例空间都有name属性,
# 但实例对象会优先在自己空间去查找

运行结果:
初入Python 面向对象~~~~学习记录

所以会有:

  • 实例对象.属性名 的查找先后顺序是:它先在自己的实例空间去找,如无;再到类空间去找,如无;再到该类所继承的类中去找;如都无,那就报错~~~~~~~
  • 对象通过句点符调用属性和方法 : 对象.属性/方法
    代码:
class Student(object):
    # 类属性
    name = "华子"

    def eat(self):
        print('华子在吃饭')

    def sleep(self):
        print('华子要睡觉')


s = Student() 
print(s.name)  # 对象调用属性
s.eat()  # 调用方法

运行结果:
初入Python 面向对象~~~~学习记录

三、方法

- 实例方法

有self的方法就是实例方法,但是self这个名字并不是不变的,它可以是其他值,但规范习惯用self了,
self表示当前对象

  1. self并不是一个关键字,其实可以是任意的标识符,为了表达代表的是当前对象自己,习惯用self
  2. 调用实例函数的时候,self不需要手动传参,系统会自动传递当前的对象.
  3. 哪个对象调用了方法,方法里的self指的就是谁。
    实例方法调用:
    代码:
class Student(object):
    # 类属性
    class_num = 30
    class_name = '8班'

    # 方法
    def __init__(self, name, course):
        self.name = name
        self.course = course

    def listen(self):
        print('%s在听%s课' % (self.name, self.course))  # self 中有name,course

    def homework(self):
        print('%s在写%s课作业' % (self.name, self.course))


s1 = Student('华仔', 'python')  # 实参传入
s1.listen()

s2 = Student('我', 'python')
s2.homework()

在上面的代码中:s1.listen() ,这个调用方法,解释器会将 s1 这个对象作为实参传给该方法的第一个形参(self).

- 静态方法

代码:

class Sum(object):

    @staticmethod
    def add(x, y):   # 这里是没有self这个参数的
        return x + y


# 实例对象调用静态方法:
s = Sum()
print(s.add(2, 6))

# 类对象调用静态方法:
print(Sum.add(6, 6))

运行结果:
初入Python 面向对象~~~~学习记录

- 类方法

代码:

class Sum(object):
    # 类属性
    num = 30

    @classmethod
    def add_num(cls):  # 这里加了 @classmethod 后,解释器会自动加上 cls 这个参数。
        print(id(Sum), id(cls))
        cls.num += 1


Sum.add_num()
print(Sum.num)

结果:
初入Python 面向对象~~~~学习记录
在上面发现:参数cls与Sum类的地址相同。所以cls就是当前的类对象。Sum这个类对象作为cls的接收者。

四、类的继承

- 继承:

继承:是子类复用父类的属性和方法的机制。在Python中,新建的类可以继承一个或多个父类。注意:object 是 Python 中所有类的根类
单继承:子类之继承一个父类,被称为单继承。
多继承:子类可以拥有多个父类,并且具有所有父类的属性和方法。

  • 父类: 又可称为基类超类
  • 新建的类: 称为派生类子类

代码:
简单例子:

 class Animal(object):
    def eat(self):
        print('吃')

    def sleep(self):
        print('睡')


class Dog(Animal):  # 继承 Animal 父类
    def bark(self):
        print('狂吠')


class Cat(Animal):
    def climetree(self):
        print('爬树')


s1 = Dog()
s2 = Cat()
s1.eat()
s2.sleep()

结果:
初入Python 面向对象~~~~学习记录
子类没有的属性可以到他继承的父类里去找。

- 继承中的方法覆盖

代码:


class Animal(object):
    def eat(self):
        print('吃')

    def sleep(self):
        print('睡')


class Dog(Animal):  # 继承 Animal 父类
    def bark(self):
        print('狂吠')

    def sleep(self):
        print('睡睡睡睡。。。。。')  # 虽然继承了父类的sleep,但子类写了个sleep方法,就覆盖了,但对父类不影响


class Cat(Animal):
    def climetree(self):
        print('爬树')


s1 = Dog()
s1.sleep()

s2 = Cat()
s2.sleep()

运行结果:
初入Python 面向对象~~~~学习记录

- 引用父类方法

  • 例子1 :
 class Animal(object):

    def __init__(self):
        self.parent = '我是父类'
        print(id(self))
        print('父类')

    def sleep(self):
        print('我是父类的睡')


class Dog(Animal):  # 继承 Animal 父类

    def sleep(self):
        super(Dog, self).sleep()  # super 会首先找到 Dog 的父类(就是类 Animal),然后把类Dog的对象(s)转换为类Animal的对象(self),因为他们的id值相同
        print('我是子类的睡睡睡睡。。。。。')
        print(self.parent) # 找到父类的parent属性


d = Dog()  # 别忘了,它会找__init__方法
d.sleep()
print(id(d))

运行结果:
初入Python 面向对象~~~~学习记录
注意:super 会首先找到 Dog 的父类(就是类 Animal),然后把类Dog的对象(s)转换为类Animal的对象(self),因为他们的id值相同

  • 例子2 :
class Parent(object):
    def __init__(self):
        self.parent = '我是父类'
        print(id(self))
        print('父类')

    def bar(self):
        print("我是父类的bar")


class Child(Parent):
    def __init__(self):
        # super(Child,self) 首先找到 Child 的父类(就是类 Parent),然后把类Child的对象(s)转换为类Parent的对象(self),他们的id值相同。
        super().__init__()  # super(Child, self).__init__()
        print('子类')

    def bar(self):
        super().bar()  # super().bar(message)
        print('我是子类的bar')
        print(self.parent) # Child的对象(s)已经转换为类Parent的对象(self)


s = Child()  # 实例化 Child 对象
s.bar()  # 调用s的bar方法
print(id(s))

运行结果:
初入Python 面向对象~~~~学习记录
super().init() # 也可以写成: super(Child, self).init() 。

- 类的多重继承

代码:

class Animal(object):
    def eat(self):
        print('吃')


class Fly(object):
    def fly(self):
        print('飞')


class Dog(object):
    pass


class BigBird(Animal, Dog, Fly):
    pass


class LittleBird(Fly, Animal):
    pass

b = BigBird()
b.fly()

c = LittleBird()
c.fly()

运行结果:
初入Python 面向对象~~~~学习记录
对于多个类的继承时,子类继承是有顺序的:从左向右继承

再就是:

  • type()方法 : 除了判断字符串等类型,它还可以判断 实例对象是属于那个类。
print(type(b))
print(type(c))

结果
初入Python 面向对象~~~~学习记录

  • isinstance()方法 : 判断某个对象是不是某个类的实例,是就True,否就False,但如果是true,那他继承的父类也是true.
    代码:
print(isinstance(b, BigBird))
print(isinstance(b, Fly))
print(isinstance(b, LittleBird))

运行结果:
初入Python 面向对象~~~~学习记录

- dir(object)和object.dict

  • dir(object) 和 object.dir() 是等价的。dir()方法可获取对象的所有属性和方法,并以列表形式返回。
print(dir(b))
print(c.__dir__())  

结果
初入Python 面向对象~~~~学习记录
他们返回的顺序不同,但内容是一样的。~~~~

  • object__dict__ 它可以获取对象自定义的属性,且以字典形式返回。
    代码:
print(c.__dict__)

运行结果:
初入Python 面向对象~~~~学习记录
注意的是:在dir(object)中,它相当于只是拿出了key,在object__dict__ 中它将 key 和 value都拿出来了。

五、练习

初入Python 面向对象~~~~学习记录

上一篇:二叉搜索树的插入和删除


下一篇:java类的继承