【Python】基础篇之面向对象

面向对象

面向对象有三大特征:封装、继承和多态,在认识这三大特征之前,需要先对类和对象有一个初步的了解。

类和对象

同C++,是多个类似事物组成的群体的统称,能够帮助我们快速处理判断事物的性质。

类的创建

# 语法及组成
class stu :
	# 包含以下内容
	# 类属性
	# 实例方法
	# 静态方法
	# 类方法
	pass	# 这里以 pass 代表上述所有语句

举例:

class Stu:  # 关于类名称的写法,通常采用驼峰式写法
    # 类属性
    name = 'jack'

    def __init__(self, age):
        self.age = age

    # 实例方法
    def print_name(self):
        print(self.name)

    def print_age(self):
        print(self.name, ' :', self.age)

    # 类方法
    @classmethod
    def fun_class(cls):
        print('调用类方法!')

    # 静态方法
    @staticmethod
    def fun1_static_fun():
        print('调用静态方法!')


对象的创建

对象的创建又称为类的实例化

语法:

实例名 = 类名()

例子:

 student = Stu(10)

有了实例,就可以调用类中的内容。

举例:

# 接上面的内容
student = Stu(10)
student.print_name()
student.print_age()
student.__init__(30)
Stu.print_age(student)

运行结果:

jack
jack  : 10
jack  : 30

类属性、类方法、静态方法

1、类属性:

类中方法外的变量称为类属性,被该类的所有对象共享。(类似C++中的public

2、类方法:

使用@classmethod修饰的方法,使用类名直接访问的方法

3、静态方法

使用@staticmethod修饰的方法,使用类名直接访问的方法

举例:

# 接上面内容
Stu.fun1_static_fun()
Stu.fun_class()

运行结果:

调用静态方法!
调用类方法!

动态绑定属性和方法

Python是动态语言,在创建对象之后,可以动态的绑定属性和方法。

举例:

# 类的创建之动态绑定属性和方法
class Student:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def print_info(self):
        print(self.name, ':', self.age)


def show():
    print('动态绑定方法成功!')


# 为了代码书写的的规范性,类与函数之间间隔2行
if __name__ == '__main__':
    stu1 = Student('jack', 20)
    stu1.print_info()
    # 动态绑定属性
    stu1.gender = '♂'
    print(stu1.gender)
    # 动态绑定方法
    stu1.show = show
    stu1.show()

运行结果:

jack : 20
♂
动态绑定方法成功!

封装

封装可以提高程序的安全性

1、将属性和行为包装到类对象中。在方法内部对属性进行操作,在类对象的外部调用方法,这样就无需关注内部的实现细节,隔离了复杂度。

2、在Python中没有专门的修饰符用于属性的私有化,如果该属性不希望在类对象外部被访问,其前面加两个_,即(__)。【但其实这种方式并不代表在类外就完全不能访问了,也可以通过_类名称__类属性(方法)的方式访问】

举例:

class Student:
    def __init__(self, name, __age):    # 不希望age在类外被访问
        self.name = name
        self.__age = __age

    def show(self):
        print(self.name, ':', self.__age)


if __name__ == '__main__':
    stu1 = Student('jack', 30)
    stu1.show()
    print(stu1.name)
    # print(stu1.__age)	# 会提示报错	AttributeError
    print(stu1._Student__age)	# 这种方式虽然可以访问,但编译器仍然会给出警告,告诉你这是一种保护成员的访问类

运行结果:

jack : 30
jack
30

继承

继承提高代码的复用性。

1、语法格式:

class 子类类名(父类1, 父类2....):
	pass

2、如果一个类没有继承任何类,则默认继承object

3、Python支持多继承

4、定义子类时,必须在其构造函数中调用父类的构造函数。

例子:

# 继承
class Animal:
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def show(self):
        print(self.name, self.age)


class FlyAnimal(Animal):
    def __init__(self, name, age, type_name):
        super().__init__(name, age)     # 使用 supper() 可以避免重复的定义语句
        self.type_name = type_name

    def show(self):	# 方法的重写
        print(self.name, self.age, self.type_name)


if __name__ == '__main__':
    an1 = FlyAnimal('麻雀', '2', '飞行')
    an1.show()

运行结果:

麻雀 2 飞行
方法重写

1、如果子类对继承来自父类的某个属性或者方法不满意,可以在子类中对其重新编写

2、子类重写后的方法可以通过supper().FunName()调用父类中被重写的方法。

例子可以参考上面的部分代码。

Object类

1、object类时所有类的父亲,因此所有类都有object类的属性和方法、

2、内置函数dir()可以查看指定对象所有属性

3、object有一个__str__()方法,用于返回一个对于"对象的描述",对应于内置函数str()经常用于print()方法,帮我们查看对象的信息,所以我们经常会对__str__() 进行重写。

至于区别的话,这里举个例子:

# 继承之 Object
class Person(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def show(self):
        print(self.name, self.age)


class Student(Person):
    def __init__(self, name, age, uid):
        super().__init__(name, age)
        self.uid = uid

    def show(self):
        super().show()
        print('uid = ', self.uid)

    # def __str__(self):  # 对象的描述
    #     return '__str__()已经被改写'


if __name__ == '__main__':
    stu1 = Student('jack', 20, '001')
    stu1.show()
    o = object()
    # print('显示object的属性:', dir(o))
    # print('显示Student的属性:', dir(Student))
    # 未重写 __str__()之前的输出
    print('未重写 __str__()之前的输出')
    print(stu1)

运行结果:

jack 20
uid =  001
未重写 __str__()之前的输出
<__main__.Student object at 0x00000270181D4EE0>

class的注释部分取消后:

代码:

# 继承之 Object
class Person(object):
    def __init__(self, name, age):
        self.name = name
        self.age = age

    def show(self):
        print(self.name, self.age)


class Student(Person):
    def __init__(self, name, age, uid):
        super().__init__(name, age)
        self.uid = uid

    def show(self):
        super().show()
        print('uid = ', self.uid)

    def __str__(self):  # 对象的描述
        return '__str__()已经被改写'


if __name__ == '__main__':
    stu1 = Student('jack', 20, '001')
    stu1.show()
    o = object()
    # 重写 __str__()之前的输出
    print('重写 __str__()之前的输出')
    print(stu1)

运行结果:

jack 20
uid =  001
重写 __str__()之前的输出
__str__()已经被改写

多态

多态提高程序的可扩展性和可维护性。

即便不知道一个变量所引用的对象到底是什么类型,仍然可以通过这个变量调用方法,在运行的过程中根据变量所引用对象的类型,动态决定带哦用哪个对象中的方法。

举例:

# 多态
class Animal:
    def eat(self):
        print('动物吃草')


class Dog(Animal):
    def eat(self):
        print('狗吃骨头....')


class Person:
    def eat(self):
        print('人吃五谷杂粮....')


def fun(obj):
    obj.eat()


fun(Dog())
fun(Person())

运行结果:

狗吃骨头....
人吃五谷杂粮....
静态语言和动态语言
静态语言和动态语言关于多态的区别

Ⅰ、静态语言实现多态的三个必要条件

1、继承

2、方法重写

3、父类引用指向子类对象

Ⅱ、动态语言不关心对象的类型,只关心对象的行为

特殊方法和特殊属性

名称描述
特殊属性__dict__获得类对象或者实例对象所绑定的所有属性和方法字典
特殊属性__bases__返回类的父类元素
特殊属性__mro__返回类的结构层次
特殊属性__subclass__()返回子类的列表
特殊方法__len__()通过重写该方法,然内置函数len()的参数可以是自定义类型
特殊方法__add__()通过重写该方法,可以让自定义对象具有+的功能
特殊方法__new__()用于创建对象
特殊方法__init__()对创建的对象进行初始化
特殊方法的举例:
# 特殊方法
class Person(object):
    def __init__(self, name, age):  # 对其本来的 __init__()进行了重写
        self.name = name
        self.age = age

    def show(self):
        print(self.name, self.age)


p1 = Person('Kang', 20)
print(p1.__dict__)
print(Person.__bases__)

运行结果:

{'name': 'Kang', 'age': 20}
(<class 'object'>,)
特殊方法的举例:
# 特殊方法
lst1 = range(1, 10)     # 生成序列 1 2 3 4 5 6 7 8 9
print(lst1.__len__())	# __len__()计算lst1的长度
a = lst1[0]
b = a.__add__(lst1[-1])     # 序列的首尾相加
print(b)


class Student:
    def __init__(self, math, chin):
        self.math = math
        self.chin = chin

    def __add__(self, other):	# 重写__add__()
        return self.math + self.chin + other.math + other.chin


运行结果:

9
10
80
__new__()和__init__()创建对象
# __new__() 和 __init__()
class Person:
    def __new__(cls, *args, **kwargs):
        print('调用___new__(),且其cls的id为{0}'.format(id(cls)))
        obj = super().__new__(cls)     # 创建一个对象
        print("创建对象的id为:{0}".format(id(obj)))
        return obj

    def __init__(self, name, age):
        print('调用__init__(),self 的id为:{0}'.format(id(self)))
        self.name = name
        self.age = age


if __name__ == '__main__':
    # 在未创建对象之前
    print('object这个对象的id为{0}'.format(id(object)))
    print('Person这个类的id为{0}'.format(id(Person)))
    p1 = Person('jack', 20)
    print('p1的id为{0}'.format(id(p1)))

运行结果:

object这个对象的id为140717576510976
Person这个类的id为1823064928464
调用___new__(),且其cls的id为1823064928464
创建对象的id为:1823064743552
调用__init__(),self 的id为:1823064743552
p1的id为1823064743552

通过上面程序运行的id变化可知,创建新对象的过程就是先通过__new__()再通过__init__()

类的浅拷贝和深拷贝

1、变量的赋值操作

只是形成两个变量,实际上还是指向同一个对象

2、浅拷贝

Python的拷贝一般都是浅拷贝,拷贝的时候,对象包含的子对象内容不拷贝,因此,源对象与拷贝对象会引用同一个子对象

3、深拷贝

使用copy模块和deepcopy函数,递归拷贝对象中包含的子对象、源对象和拷贝对象所有子对象也不相同。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值