您好!此笔记的文本和代码以网盘形式分享于文末!
因个人能力有限,错误处欢迎大家交流和指正!基础部分内容简单,但多且零散!
#!/usr/bin/env python
# -*- coding:utf-8 -*-
"""
面向对象:
"""
"""
类(Class):
用来描述具有相同的属性和方法的对象的集合。
它定义了该集合中每个对象所共有的属性和方法。
对象是类的实例。
class 类名:
'类的文档字符串'
类体
"""
# # 创建一个类
# class Data:
# pass
#
#
# class Person:
# role = 'person' # 角色属性
#
# def walk(self): # 方法,动态属性
# print("person is walking...")
#
#
# # 属性的引用
# # 查看人的role属性
# print(Person.role)
# # 引用人的走路方法,注意,这里不是在调用
# print(Person.walk)
# # 实例化: 类名加括号就是实例化
# class Person:
# role = 'person' # 角色属性
#
# def __init__(self, name):
# self.name = name
#
# def walk(self): # 方法,动态属性
# print("person is walking...")
#
#
# # 实例化的过程就是类——>对象的过程 egg 为对象
# # 语法:对象名 = 类名(参数)
# egg = Person('egon')
# # 查看对象的属性和调用方法
# print(egg.name)
# egg.walk()
# print(egg.walk())
"""
class 类名:
def __init__(self,参数1,参数2):
self.对象的属性1 = 参数1
self.对象的属性2 = 参数2
def 方法名(self):pass
def 方法名2(self):pass
对象名 = 类名(1,2) #对象就是实例,代表一个具体的东西
#类名() : 类名+括号就是实例化一个类,相当于调用了__init__方法
#括号里传参数,参数不需要传self,其他与init中的形参一一对应
#结果返回一个对象
对象名.对象的属性1 #查看对象的属性,直接用 对象名.属性名 即可
对象名.方法名() #调用类中的方法,直接用 对象名.方法名() 即可
"""
# # 创建一个狗类
# class Dog:
# role = 'dog'
#
# def __init__(self, name, breed, aggressivity, life_value):
# self.name = name # 每一只狗都有自己的昵称;
# self.breed = breed # 每一只狗都有自己的品种;
# self.aggressivity = aggressivity # 每一只狗都有自己的攻击力;
# self.life_value = life_value # 每一只狗都有自己的生命值;
#
# def attack(self, animal):
# # 狗被攻击,狗的生命值会下降
# animal.life_value -= self.aggressivity
#
#
# # 实例化二哈
# ha1 = Dog('大二哈', '哈士奇', 10, 1000)
# ha2 = Dog('小二哈', '哈士奇', 7, 800)
# # 交互
# print(ha1.life_value)
# print(ha2.life_value)
#
# ha1.attack(ha2)
# ha2.attack(ha1)
#
# print(ha1.life_value)
# print(ha2.life_value)
# # 计算圆的周长和面积
# from math import pi
#
#
# class Circle:
# """
# 定义了一个圆形类;
# 提供计算面积(area)和周长(perimeter)的方法
#
# """
# # 圆的半径
# def __init__(self, radius):
# self.radius = radius
#
# def area(self):
# return pi * self.radius * self.radius
#
# def perimeter(self):
# return 2 * pi * self.radius
#
#
# # 实例化一个圆
# circle = Circle(10)
# # 计算对象圆的面积
# area1 = circle.area()
# # 计算对象圆的周长
# per1 = circle.perimeter()
# # 打印圆面积和周长
# print(area1, per1)
"""
创建一个类就会创建一个类的名称空间
类的静态属性和动态属性:
静态属性就是直接在类中定义的变量
动态属性就是定义在类中的方法
类的数据属性是共享给所有对象的,地址相同
类的动态属性是绑定到所有对象的,地址不同
"""
# # 类的组合指的是,在一个类中以另外一个类的对象作为数据属性
# class Weapon:
# # 这是该装备的主动技能
# def prick(self, obj):
# obj.life_value -= 500
#
#
# class Person:
# role = 'person'
#
# def __init__(self, name):
# self.name = name
# # 给角色绑定一个武器;Weapon实例化为Person的一个属性
# self.weapon = Weapon()
#
#
# egg = Person('egon')
# # 直接egg.weapon来使用组合类中的所有方法
# egg.weapon.prick()
# # 圆环的面积周长的组合类
# from math import pi
#
#
# class Circle:
# """
# 定义了一个圆形类;
# 提供计算面积(area)和周长(perimeter)的方法
# """
# def __init__(self, radius):
# self.radius = radius
#
# def area(self):
# return pi * self.radius * self.radius
#
# def perimeter(self):
# return 2 * pi * self.radius
#
#
# class Ring:
# """
# 定义了一个圆环类
# 提供圆环的面积和周长的方法
# """
# def __init__(self, radius_outside, radius_inside):
# self.outside_circle = Circle(radius_outside)
# self.inside_circle = Circle(radius_inside)
#
# def area(self):
# return self.outside_circle.area() - self.inside_circle.area()
#
# def perimeter(self):
# return self.outside_circle.perimeter() + self.inside_circle.perimeter()
#
#
# ring = Ring(10, 5)
# # 计算环形的周长
# print(ring.perimeter())
# # 计算环形的面积
# print(ring.area())
# # 类与组合的类之间的关系,它是一种“有”关系
# # 当类之间有显著不同,且较小的类是较大的类所需要的组件
# class BirthDate:
# """
# 关于生日信息的类,年月日
# """
# def __init__(self, year, month, day):
# self.year = year
# self.month = month
# self.day = day
#
#
# class Couse:
# """
# 课程信息的类,名称价格周期
# """
# def __init__(self, name, price, period):
# self.name = name
# self.price = price
# self.period = period
#
#
# class Teacher:
# """
# 教师信息的类,姓名性别生日授课
# """
# def __init__(self, name, gender, birth, course):
# self.name = name
# self.gender = gender
# self.birth = birth
# self.course = course
#
# def teach(self):
# print('teaching')
#
#
# t1 = Teacher('egon', 'male',
# BirthDate('1995', '1', '27'),
# Couse('python', '28000', '4 months')
# )
#
# print(t1.birth.year, t1.birth.month, t1.birth.day)
# print(t1.course.name, t1.course.price, t1.course.period)
# print(t1.birth)
# # 人狗大战
# class Person:
# """
# 定义一个人的类, 姓名攻击力生命值金钱
# """
# role = 'person'
#
# def __init__(self, name, aggressivity, life_value, money):
# self.name = name
# self.aggressivity = aggressivity
# self.life_value = life_value
# self.money = money
#
# def attack(self, dog):
# """
# 定义了人的一个攻击的方法
# """
# dog.life_value -= self.aggressivity
#
#
# class Dog:
# """
# 定义一个狗的类,昵称品种攻击力生命值
# """
# role = 'dog' # 狗的角色属性都是狗
#
# def __init__(self, name, breed, aggressivity, life_value):
# self.name = name
# self.breed = breed
# self.aggressivity = aggressivity
# self.life_value = life_value
#
# def bite(self, people):
# """
# 定义了一个攻击方法
# """
# people.life_value -= self.aggressivity
#
#
# class Weapon:
# """
# 定义了一个武器,名称价格攻击附加耐久值
# """
# def __init__(self, name, price, aggrev, life_value):
# self.name = name
# self.price = price
# self.aggrev = aggrev
# self.life_value = life_value
#
# def update(self, obj):
# """
# 定义使用武器附加的方法
# """
# obj.money -= self.price
# obj.aggressivity += self.aggrev
# obj.life_value += self.life_value
#
# def prick(self, obj):
# """
# 定义一个攻击技能的方法
# """
# obj.life_value -= 500
#
#
# # 实例化武器、狗、人
# lance = Weapon('长矛', 200, 6, 100)
# egg = Person('egon', 10, 1000, 600)
# ha2 = Dog('大哈', '哈士奇', 10, 1000)
#
# # 购置装备
# if egg.money > lance.price:
# lance.update(egg)
# egg.weapon = lance
#
# print(egg.money, egg.life_value, egg.aggressivity)
#
# print(ha2.life_value)
# # 这里自带了武器的攻击附加伤害
# egg.attack(ha2)
# print(ha2.life_value)
# # 发动武器技能加成
# egg.weapon.prick(ha2)
# print(ha2.life_value)
# # 类的继承
# # 定义父类1
# class ParentClass1:
# pass
#
#
# # 定义父类2
# class ParentClass2:
# pass
#
#
# # 单继承
# # 基类是ParentClass1,派生类是SubClass
# class SubClass1(ParentClass1):
# pass
#
#
# # python支持多继承,用逗号分隔开多个继承的类
# class SubClass2(ParentClass1, ParentClass2):
# pass
#
#
# print(SubClass1.__bases__)
# print(SubClass2.__bases__)
# # 无指定基类,默认继承object类,其是所有python类的基类
# print(ParentClass1.__bases__)
# # 抽象:即抽取类似或者说比较像的部分。
# # 继承是基于抽象的结果,通过继承的方式表达出抽象的结构
# # 将奥巴马和梅西这俩对象比较像的部分抽取成类;
# # 将人,猪,狗这三个类比较像的部分抽取成父类。
# # 抽象是分析过程,继承是实现方式
# class Animal:
#
# def eat(self):
# print("%s 吃 " % self.name)
#
# def drink(self):
# print("%s 喝 " % self.name)
#
#
# class Cat(Animal):
#
# def __init__(self, name):
# self.name = name
# self.breed = '猫'
#
# def climb(self):
# print('爬树')
#
#
# class Dog(Animal):
#
# def __init__(self, name):
# self.name = name
# self.breed = '狗'
#
# def look_after_house(self):
# print("%s " '汪汪叫' % self.name)
#
#
# c1 = Cat('小白猫')
# c1.eat()
#
# d1 = Dog('大金毛')
# d1.drink()
#
# d2 = Dog('帅边牧')
# d2.look_after_house()
# # 派生,子类可添加新的属性或重新定义这些属性
# # 重新定义的属性不会影响到父类
# class A:
# def hahaha(self):
# print('A')
#
#
# class B(A):
# def hahaha(self):
# super().hahaha()
# print('B')
#
#
# class C(A):
# def hahaha(self):
# print('C')
#
#
# class D(A):
# def hahaha(self):
# print('D')
#
# def newmethod(self):
# print("派生,新属性")
#
#
# a = A()
# b = B()
# c = C()
# d = D()
# a.hahaha()
# print("---***---")
# b.hahaha()
# print("---***---")
# c.hahaha()
# print("---***---")
# super(B, b).hahaha()
# print("---***---")
# d.hahaha()
# d.newmethod()
# 接口类,借用abc模块来实现接口
# 接口继承实质上是要求“做出一个良好的抽象,
# 这个抽象规定了一个兼容接口,
# 使得外部调用者无需关心具体细节,
# 可一视同仁的处理实现了特定接口的所有对象”
# ——这在程序设计上,叫做归一化。
# 归一化,让使用者无需关心对象的类是什么,
# 只需要的知道这些对象都具备某些功能
# # 抽象类是一个特殊的类,它的特殊之处在于只能被继承,不能被实例化
# # 子类必须实现抽象方法
# # 需要借助模块abc来实现
# import abc
#
#
# class All_file(metaclass=abc.ABCMeta):
# all_type = 'file'
#
# @abc.abstractmethod # 定义抽象方法,无需实现功能
# def read(self):
# # 子类必须定义读功能
# pass
#
# @abc.abstractmethod
# def write(self):
# # 子类必须定义些功能
# pass
#
#
# # 子类继承抽象类,但是必须定义read和write方法
# class Txt(All_file):
# def read(self):
# print('文本数据的读取方法')
#
# def write(self):
# print('文本数据的写入方法')
#
#
# # 子类继承抽象类,但是必须定义read和write方法
# class Process(All_file):
# def read(self):
# print('进程数据的读取方法')
#
# def write(self):
# print('进程数据的写入方法')
#
#
# wenbenwenjian = Txt()
# jinchengwenjian = Process()
#
# # 这样都是被归一化了,也就是一切皆文件的思想
# wenbenwenjian.read()
# jinchengwenjian.write()
#
# print(wenbenwenjian.all_type)
# print(jinchengwenjian.all_type)
# 抽象类的本质还是类,指的是一组类的相似性包括数据属性和函数属性
# 接口强调函数属性的相似性
# 抽象类是一个介于类和接口直接的一个概念,
# 同时具备类和接口的部分特性,可以用来实现归一化设计
# 继承抽象类的过程中,我们应该尽量避免多继承;
# 继承接口的时候,我们反而鼓励你来多继承接口
# 接口隔离原则:使用多个专门的接口,而不使用单一的总接口。
# 即客户端不应该依赖那些不需要的接口。
"""
继承顺序 深度优先和广度优先
经典类:C1 和 C2 都是经典类
class C1:
pass
class C2:
pass
新式类: N1 和 N2都是新式类
class N1(object):
pass
class N2(N1):
pass
类是经典类时,多继承的情况下,会按照深度优先方式查找
类是新式类时,多继承情况下,会按照广度优先的方式查找
python3中统一都是新式类
python2中才分新式类与经典类
"""
# class A(object):
# def test(self):
# print('from A')
#
#
# class B(A):
# def test(self):
# print('from B')
#
#
# class C(A):
# def test(self):
# print('from C')
#
#
# class D(B):
# def test(self):
# print('from D')
#
#
# class E(C):
# def test(self):
# print('from E')
#
#
# class F(D, E):
# # def test(self):
# # print('from F')
# pass
#
#
# f1 = F()
# f1.test()
# # 只有新式才有这个属性可以查看线性列表,经典类没有这个属性
# print(F.__mro__)
"""
继承的作用:
# 减少代码的重用
# 提高代码可读性
# 规范编程模式
抽象:抽象即抽取类似或者说比较像的部分。是一个从具题到抽象的过程。
继承:子类继承了父类的方法和属性
派生:子类在父类方法和属性的基础上产生了新的方法和属性
1.多继承问题
在继承抽象类的过程中,我们应该尽量避免多继承;
而在继承接口的时候,我们反而鼓励你来多继承接口
2.方法的实现
在抽象类中,我们可以对一些抽象方法做出基础实现;
而在接口类中,任何方法都只是一种规范,具体的功能需要子类实现
"""
"""
多态指的是一类事物有多种形态
多态性(多态动态绑定)
多态性是指在不考虑实例类型的情况下使用实例
"""
# # 动物有多种形态:狗,猫,猪
# import abc
#
#
# # 同一类事物:动物
# class Animal(metaclass=abc.ABCMeta):
# @abc.abstractmethod
# def talk(self):
# pass
#
#
# # 动物的形态之一:人
# class Cat(Animal):
# def talk(self):
# print('喵喵')
#
#
# # 动物的形态之二:狗
# class Dog(Animal):
# def talk(self):
# print('汪汪')
#
#
# # 动物的形态之三:猪
# class Pig(Animal):
# def talk(self):
# print('猪昂昂')
#
#
# c1 = Cat()
# d1 = Dog()
# p1 = Pig()
#
# # c1、d1、p1都是动物,只要是动物肯定有talk方法
# # 于是我们可以不用考虑它们三者的具体是什么类型,而直接使用
# c1.talk()
# d1.talk()
# p1.talk()
#
#
# # 更进一步,我们可以定义一个统一的接口来使用
# def func(obj):
# obj.talk()
#
#
# func(c1)
"""
封装:隐藏对象的属性和实现细节,仅对外提供公共访问方式。
优点:
1. 将变化隔离;
2. 便于使用;
3. 提高复用性;
4. 提高安全性;
封装的原则:
1. 将不需要对外提供的内容都隐藏起来;
2. 把属性都隐藏,提供公共方法对其访问。
私有变量和私有方法:
在python中用双下划线开头的方式将属性隐藏起来(设置成私有的)
封装在于明确区分内外,使得类实现者可以修改封装内的东西而不影响外部调用者的代码;
"""
# 其实这仅仅这是一种变形操作
# 类中所有双下划线开头的名称如__x都会自动变形成:_类名__x的形式:
class A:
# 类的数据属性就应该是共享的,
# 但是语法上是可以把类的数据属性设置成私有的如__N,会变形为_A__N
__N = 0
def __init__(self):
# 变形为self._A__X
self.__X = 10
# 变形为_A__foo
def __foo(self):
print('from A')
def bar(self):
# 只有在类内部才可以通过__foo的形式访问到.
self.__foo()
# A._A__N是可以访问到的,
# 即这种操作并不是严格意义上的限制外部访问,
# 仅仅只是一种语法意义上的变形
"""
变形的特点:
1.类中定义的__x只能在内部使用,如self.__x,引用的就是变形的结果。
2.这种变形其实正是针对外部的变形,在外部是无法通过__x这个名字访问到的。
3.在子类定义的__x不会覆盖在父类定义的__x,因为子类中变形成了:
_子类名__x,而父类中变形成了:_父类名__x,
即双下滑线开头的属性在继承给子类时,子类是无法覆盖的。
注意问题:
1.这种机制也并没有真正意义上限制我们从外部直接访问属性,
知道了类名和属性名就可以拼出名字:_类名__属性,然后就可以访问了,如a._A__N
2.变形的过程只在类的内部生效,在定义后的赋值操作,不会变形
3.在继承中,父类如果不想让子类覆盖自己的方法,可以将方法定义为私有的
"""
"""
property是一种特殊的属性,访问它时会执行一段功能(函数)然后返回值
将一个类的函数定义成property特性以后,使用obj.name的时候,
无法察觉name是执行了一个函数然后计算出来的,这种特性的使用方式遵循了统一访问的原则
一个静态属性property本质就是实现了get,set,delete三种方法
面向对象的封装有三种方式:
【public】
这种其实就是不封装,是对外公开的
【protected】
这种封装方式对外不公开,但对朋友(friend)或者子类(形象的说法是“儿子”,
但我不知道为什么大家 不说“女儿”,
就像“parent”本来是“父母”的意思,但中文都是叫“父类”)公开
【private】
这种封装对谁都不公开
"""
# # 计算圆的周长和面积
# from math import pi
#
#
# class Circle:
# """
# 定义了一个圆形类;
# 提供计算面积(area)和周长(perimeter)的方法
#
# """
# # 圆的半径
# def __init__(self, radius):
# self.radius = radius
#
# @property
# def area(self):
# return pi * self.radius * self.radius
#
# @property
# def perimeter(self):
# return 2 * pi * self.radius
#
#
# # 实例化一个圆
# c = Circle(10)
# # 计算对象圆的面积和周长并打印
# print(c.area, c.perimeter)
# # 此时的特性area和perimeter不能被赋值
# class Foo:
# def __init__(self, val):
# # 将所有的数据属性都隐藏起来
# self.__NAME = val
#
# @property
# def name(self):
# # obj.name访问的是self.__NAME(这也是真实值的存放位置)
# return self.__NAME
#
# @name.setter
# def name(self, value):
# # 在设定值之前进行类型检查
# if not isinstance(value, str):
# raise TypeError('%s must be str' % value)
# # 通过类型检查后,将值value存放到真实的位置self.__NAME
# self.__NAME = value
#
# @name.deleter
# def name(self):
# raise TypeError('Can not delete')
#
#
# f = Foo('egon')
# print(f.name)
# # 抛出异常'TypeError: 10 must be str'
# f.name = 10
# # 抛出异常'TypeError: Can not delete'
# del f.name
# # 一个静态属性property本质就是实现了get,set,delete三种方法
# class Foo:
#
# @property
# def AAA(self):
# print('get的时候运行我啊')
#
# @AAA.setter
# def AAA(self,value):
# print('set的时候运行我啊')
#
# @AAA.deleter
# def AAA(self):
# print('delete的时候运行我啊')
#
#
# # 只有在属性AAA定义property后才能定义AAA.setter,AAA.deleter
# f1 = Foo()
# f1.AAA
# f1.AAA = 'aaa'
# del f1.AAA
# class Foo:
# def get_AAA(self):
# print('get的时候运行我啊')
#
# def set_AAA(self,value):
# print('set的时候运行我啊')
#
# def delete_AAA(self):
# print('delete的时候运行我啊')
# # 内置property三个参数与get,set,delete一一对应
# AAA = property(get_AAA, set_AAA, delete_AAA)
#
#
# f1 = Foo()
# f1.AAA
# f1.AAA = 'aaa'
# del f1.AAA
# 使用方式
# class Goods:
#
# def __init__(self):
# # 原价
# self.original_price = 100
# # 折扣
# self.discount = 0.8
#
# @property
# def price(self):
# # 实际价格 = 原价 * 折扣
# new_price = self.original_price * self.discount
# return new_price
#
# @price.setter
# def price(self, value):
# self.original_price = value
#
# @price.deleter
# def price(self):
# del self.original_price
#
#
# obj = Goods()
# # 获取商品价格
# # obj.price
# # 修改商品原价
# obj.price = 200
# print(obj.price)
# # 删除商品原价
# del obj.price
# obj.price = 300
# print(obj.price)
"""
封装器的作用或区别
Classmethod:
Staticmethod
"""
class Classmethod_Demo():
role = 'dog'
@classmethod
def func(cls):
print(cls.role)
Classmethod_Demo.func()
class Staticmethod_Demo():
role = 'dog'
@staticmethod
def func():
print("当普通方法用")
Staticmethod_Demo.func()
class A:
__role = 'CHINA'
@classmethod
def show_role(cls):
print(cls.__role)
@staticmethod
def get_role():
return A.__role
@property
def role(self):
return self.__role
a = A()
print(a.role)
print(a.get_role())
a.show_role()
愿有更多的朋友,在网页笔记结构上分享更逻辑和易读的形式:
链接:暂无
提取码:暂无