最新消息:XAMPP默认安装之后是很不安全的,我们只需要点击左方菜单的 "安全"选项,按照向导操作即可完成安全设置。

Python-面向对象

XAMPP下载 admin 642浏览 0评论
面向过程
面向过程:核心是过程二字,过程即解决问题的步骤
基于该思想写程序就类似流水线
优点:复杂的过程简单化
缺点:扩展性差
面向对象
面向对象:核心是对象二字,对象是特征与技能的合体
基于该思想写程序好比创建一个世界,也是有一个对象组成
优点:可扩展性搞
缺点:编程复杂度搞,容易出现过度设计
面向对象特点
将某些相关的功能(函数)封装在一起;
上帝的角度创建了一个模板,通过模板创建不同的对象;
在现实世界:一定先有一个个具体存在的对象,后总结出的类
计算机世界:一定保证先定义类后产生对象
一类包含相同的静态属性与方法的模板
对象
对象是类的实例化
#class demo
class Person:
    mind = “有思想”
    animal = “高级动物”
    language = “文字”  #静态属性
    #类的方法
    def work(self):   #self:形参角度的位置参数
        print(“人类都会工作”)
    def eat(self):     #类的方法
        print(“人类都需要吃饭”)
#结构分析:类一般分为两部分:变量 方法
#思想分析:创建一个类:创建一个公共模板通过创建个体对象可以享有公共方法
类名
类名调用静态属性
#方法1: (类名.__dict__):只能查询类中所以的静态属性
#方法2:通过(类名.静态属性名)调用
class pay:
“””
这是一个支付类
“””
    name = “支付接口”
    def pay_port(self):
    print(“我是一个支付接口”)
    def red_packet(self):
    print(“我是发红包功能”)
print(pay.__dict__)   #查看类的名称空间
#查看属性
print(pay.name)       #pay.name:类的静态属性
#增加属性
pay.country = “China”
print(pay.country)
#修改
pay.country = “china”
print(pay.country)
#删除
del pay.country
print(pay.country)
类名调用动态方法(一般不建议使用类名调用类的动态方法,除类方法与静态方法)
class pay:
“””
这是一个支付类
“””
     name = “支付接口”
     def pay_port(self):
         print(“我是一个支付接口”)
     def red_packet(self):
        print(“我是发红包功能”)
print(pay.pay_port) #调用类的动态方法
对象
对象 = 类名():一个类实例化对象的过程
实例化对象的过程:
1.对象 = 类名()调用object类的__new__方法创建一个对象
2.实例化对象在内存开辟一个对象地址空间;
3.自动执行__init__这个特殊方法,自动将对象地址空间传递给__init__方法的self参数;
4.在__init__方法中给对象地址空间封装一些静态属性
class test:
    name = “火影忍者”    #类的静态属性
    def __init__(self,name,age,ad,hp):  #__init__:对象的特殊方法(用于给对象封装静态属性):(self:对象空间的内存地址,name,age,ad,hp:对象的静态属性)
        self.name = name   #self.name = name:对象地址空间里定义一个叫name的变量接收__init__方法传递的第一个位置参数:name
        self.age = age #同上
        self.ad = ad   #同上
        self.hp = hp   #同上
    def test(self):    #类的动态方法:self = 对象的内存地址空间;
        pass
you = test(“宇智波鼬”,”男”,10000,500)
print(you.name)
类的静态属性一般通过类名调用或改变;
类的动态访问一般通过对象调用;
self Python中约定 类中的访问第一个参数要设定为slef
在对象调用方法时会自动将对象空间传递给self
对象调用类的静态属性
格式:对象.类的静态属性
class test:
    name = “火影忍者”    #类的静态属性
    def __init__(self,name,age,ad,hp):  #__init__:对象的特殊方法(给对象封装静态属性):(self:对象空间的内存地址,name,age,ad,hp:对象的静态属性)
        #self.name = name   #self.name = name:对象空间里定义一个叫name的变量接收__init__方法传递的第一个位置参数name
        self.age = age
        self.ad = ad
        self.hp = hp
    def test(self):
        pass
you = test(“宇智波鼬”,”男”,10000,500)
print(you.name)
对象调用类的动态方法
对象.类的动态方法
class test:
    name = “火影忍者”    #类的静态属性
    def __init__(self,name,age,ad,hp):  #__init__:对象的特殊方法(给对象封装静态属性):(self:对象空间的内存地址,name,age,ad,hp:对象的静态属性)
        #self.name = name   #self.name = name:对象空间里定义一个叫name的变量接收__init__方法传递的第一个位置参数name
        self.age = age
        self.ad = ad
        self.hp = hp
    def test(self,*args,**kwargs):
        print(“我是一个动态属性”)
        print(args)
        return 1
you = test(“宇智波鼬”,”男”,10000,500)
print(you.test(1,2,3,4))
对象查看自己空间的属性
查看全部:对象名.__dict__
查看对象自己的属性
print(对象名.静态属性名)
查找对象属性顺序
1.对象本身名称空间
2.类的名称空间
3.父类名称空间
1.类中定义的方法是绑定给对象使用的
2.不同的对象就是不同的绑定方法
3.绑定给谁就应该由谁调用,谁来调用就会把对象的内存地址传递给类方法里的self参数
4.对象与对象之间不能互相访问
5.类所有属性共享,所有对象内部都包含一个”类内存指针”:指向这个对象属于哪个类
类即类型
#在python中接触到的数据类型 如列表 字典 字符串等其实都是一个类
a = “test”
b = 1
c = []
d = {}
e = ()
print(type(e))
#我们拿列表举例在列表中c = [] 其实就是list这个类的对象叫c
#我们通过c.append()可以追加元素其实就是调用list类里的append()方法将元素追加到a这个对象的内存空间
面向对象–组合
组合:对象中的属性是另一个类的对象
组合的作用:让类的对象与另一个类的对象发生关联,从而互相访问
#基础代码
class test:
    “””
    模拟攻击
    “””
    name = “火影忍者”
    def __init__(self,name,ad,hp):
        self.name = name
        self.ad = ad
        self.hp = hp
    def fight(self,role1):
        role1.hp = role1.hp – self.ad
        print(“%s攻击了%s,%s掉了%s” %(self.name,role1.name,role1.name,role1.hp))
test1 = test(“鸣人”,10000,8000)
test2 = test(“佐助”,10000,6000)
test1.fight(test2)
#类的组合
class test:
    “””
    模拟攻击
    “””
    name = “火影忍者”
    def __init__(self, name, ad, hp):
        self.name = name
        self.ad = ad
        self.hp = hp
    # def fight(self, role1):
    #     role1.hp = role1.hp – self.ad
    #     print(“%s攻击了%s,%s掉了%s” % (self.name, role1.name, role1.name, role1.hp))
    def eqit_weapon(self,wea):
        self.wea = wea
class weapon:
    “””
    技能库
    “””
    def __init__(self, name, ad):
        self.name = name
        self.ad = ad
    def weapon_attack(self,role1,role2):
        role2.hp = role2.hp – self.ad
        print(“%s使用了%s攻击了%s,%s剩余%s” %(role1.name,self.name,role2.name,role2.name,role2.hp))
test1 = test(“鸣人”, 10000, 8000)
test2 = test(“佐助”, 10000, 6000)
test3 = weapon(“螺旋丸”,100)
test4 = weapon(“千鸟”,70)
test1.eqit_weapon(test3)
test2.eqit_weapon(test4)
test1.wea.weapon_attack(test1,test2)
test2.wea.weapon_attack(test2,test1)
#我们来分析一下上面都做了哪些事情
#1.test这个类实例化了test1 test2;weapon类实例化了test3 test4
#2.在内存中开辟了4个对象地址空间存放了自己的属性
#3.test1.eqit_weapon(test3):test1对象发现自己的对象空间没有eqit_weapon()方法就
#通过类内存指针找到了自己的类调用了eqit_weapon()方法并将test3的内存地址传递进去
#4.test1在自己的内存空间新建了一个静态属性:wea对应的值是test3的内存地址空间
#5.test2同理
#6.test1这个对象调用自己的内存空间里的wea属性然后指向到了test3的地址空间
#7.在test3的地址空间里通过类内存指针找到了weapon_attack()方法并将test1和test2传递进去
#8.由于调用weapon_attack()方法的属于test3所以self.name是test3内存空间里的name并不是test1里的name
类的多态
Python默认支持多态
类的类型
经典类(不继承object类)
新式类(继承object类)
Python2 经典类与新式类共存
Python3 全部都是新式类
类的继承
继承描述的是子类与父类之间的关系,是一种什么是什么的关系。要找出这种关系,必须先抽象再继承
抽象即抽取类似或者说比较像的部分。
抽象分成两个层次:
1.将奥巴马和梅西这俩对象比较像的部分抽取成类;
2.将人,猪,狗这三个类比较像的部分抽取成父类。
抽象最主要的作用是划分类别(可以隔离关注点,降低复杂度)
继承:是基于抽象的结果,通过编程语言去实现它,肯定是先经历抽象这个过程,才能通过继承的方式去表达出抽象的结构。
抽象只是分析和设计的过程中,一个动作或者说一种技巧,通过抽象可以得到
# ==========================第一部分
# 例如
# 猫可以:喵喵叫、吃、喝、拉、撒
# 狗可以:汪汪叫、吃、喝、拉、撒
# 如果我们要分别为猫和狗创建一个类,那么就需要为 猫 和 狗 实现他们所有的功能,伪代码如下:
# 猫和狗有大量相同的内容
class cat:
    def 喵喵叫(self):
        print(‘喵喵叫’)
    def 吃(self):
        print(“吃东西”)
    def 喝(self):
        print(“喝水”)
    def 拉(self):
        print(“拉了”)
class dog:
    def wangwang(self):
        print(‘旺旺叫’)
    def 吃(self):
        print(“吃东西”)
    def 喝(self):
        print(“喝水”)
    def 拉(self):
        print(“拉了”)
#== == == == == == == == == == == == == 第二部分
#上述代码不难看出,吃、喝、拉、撒是猫和狗都具有的功能,而我们却分别的猫和狗的类中编写了两次,如果使用继承的思想,如下实现:
#动物:吃、喝、拉、撒
#猫:喵喵叫(猫继承动物的功能)
#狗:汪汪叫(狗继承动物的功能)
#伪代码如下:
class 动物:
    def 吃(self):
        print(“吃东西”)
    def 喝(self):
        print(“喝水”)
    def 拉(self):
        print(“拉了”)
# do something
# 在类后面括号中写入另外一个类名,表示当前类继承另外一个类
class cat(动物):
    def 喵喵叫(self):
        print(“喵喵叫”)
# 在类后面括号中写入另外一个类名,表示当前类继承另外一个类
class dog(动物):
        def 汪汪叫(self):
            print(“汪汪叫”)
#== == == == == == == == == == == == == 第三部分
# 继承的代码实现
class Animal:
    def eat(self):
        print(“%s 吃 ” % self.name)
    def drink(self):
        print(“%s 喝 ” % self.name)
    def shit(self):
        print(“%s 拉 ” % self.name)
    def pee(self):
        print(“%s 撒 ” % self.name)
class Cat(Animal):
    def __init__(self, name):
        self.name = name
        self.breed = ‘猫’
    def cry(self):
        print(‘喵喵叫’)
class Dog(Animal):
    def __init__(self, name):
        self.name = name
        self.breed = ‘狗’
    def cry(self):
        print(‘汪汪叫’)
########## 执行 #########
c1 = Cat(‘小白家的小黑猫’)
c1.eat()
c2 = Cat(‘小黑的小白猫’)
c2.drink()
d1 = Dog(‘胖子家的小瘦狗’)
d1.eat()
# 使用继承来重用代码比较好的例子
继承与重用性
在开发程序的过程中,如果我们定义了一个类A,然后又想新建立另外一个类B,但是类B的大部分内容与类A的相同时
我们不可能从头开始写一个类B,这就用到了类的继承的概念。
通过继承的方式新建类B,让B继承A,B会‘遗传’A的所有属性(数据属性和函数属性),实现代码重用
class Hero:
    def __init__(self,nickname,aggressivity,life_value):
        self.nickname=nickname
        self.aggressivity=aggressivity
        self.life_value=life_value
    def move_forward(self):
        print(‘%s move forward’ %self.nickname)
    def move_backward(self):
        print(‘%s move backward’ %self.nickname)
    def move_left(self):
        print(‘%s move forward’ %self.nickname)
    def move_right(self):
        print(‘%s move forward’ %self.nickname)
    def attack(self,enemy):
        enemy.life_value-=self.aggressivity
class Garen(Hero):
    pass
class Riven(Hero):
    pass
g1=Garen(‘草丛伦’,100,300)
r1=Riven(‘锐雯雯’,57,200)
print(g1.life_value)
r1.attack(g1)
print(g1.life_value)
”’
运行结果
243
”’
提示:用已经有的类建立一个新的类,这样就重用了已经有的软件中的一部分设置大部分大大生了编程工作量这就是常说的软件重用,不仅可以重用自己的类也可以继承别人的,比如标准库,来定制新的数据类型这样就是大大缩短了软件开发周期,对大型软件开发来说意义重大;
class Animal:
    def __init__ (self,kind,age,sex):
        self.kind = kind
        self.age = age
        self.sex = sex
class Person(Animal):
    pass
class Dog(Animal):
    pass
class Cat(Animal):
    pass
#Animal:父类 or 基类
#Person:子类 or 派生类
单继承
class Animal:
    a1 = “测试”
    def __init__(self,kind,age,sex):
        self.kind = kind
        self.age = age
        self.sex = sex
class Person(Animal):
    a1 = “alex”
    pass
class Dog(Animal):
    pass
class Cat(Animal):
    pass
a = Person(“人类”,18,”男”)
print(a.kind)
子类有自己的属性:如何要调用父类的属性和方法又要调用子类的属性和方法
class Animal:
    def __init__(self,name,sex,age):
        self.name = name
        self.sex = sex
        self.age = age
    def eat(self):
        print(“%s正在吃饭” %(self.name))
class Person(Animal):
    def __init__(self,name,sex,age,coat_color):
        #super(Person,self).__init__(name,sex,age) python2写法
        super().__init__(name,sex,age)   # 重构父类的__init__并给父类传递需要的参数,super()是一个特殊的对象默认会把self(对象自己)传递给父类当第一个参数(父类的self),类似实例化了父类;
        self.coat_color = coat_color
    def eat(self):
        print(“%s人类%s正在吃饭” % (self.coat_color,self.name))
        super().eat() #super会按当前类的mro列表eat方法
class Dog(Animal):
    def __init__(self,coat_color):
        self.coat_color = coat_color
    def eat(self):
        print(“狗狗正在吃饭”)
p2 = Person(“王铁锤”,”女”,18,”黄色”)
p2.eat()
print(p2.mro())  #查看类的mro列表
super():是一个特殊对象,会按当前类所在mro列表中的位置的下一个类开始查找动态方法或静态属性
多继承
新式类:c3算法 mro 主要查询新式类多类继承的继承顺序
class Base:
    def __init__(self):
        print(‘Base.__init__’)
class A(Base):
    def __init__(self):
        super().__init__()
        print(‘A.__init__’)
class B(Base):
    def __init__(self):
        super().__init__()
        print(‘B.__init__’)
class C(A,B):
    def __init__(self):
        super().__init__()  # Only one call to super() here
        print(‘C.__init__’)
c = C()
print(C.mro())  #查看可的MON列表
对于定义的每一个类,Python会计算出一个所谓的方法解析顺序(MRO)列表;这个MRO列表就是一个简单的所有基类的线性顺序表。例如:
print(C.mro())
>>>[<class ‘__main__.C’>, <class ‘__main__.A’>, <class ‘__main__.B’>, <class ‘__main__.Base’>, <class ‘object’>]
为了实现继承,Python会在MRO列表上从左到右开始查找基类,直到找到第一个匹配这个属性的类为止。
而这个MRO列表的构造是通过一个C3线性化算法来实现的。 我们不去深究这个算法的数学原理,它实际上就是合并所有父类的MRO列表并遵循如下三条准则:
子类会先于父类被查找
多个父类会根据它们在列表中的从坐到右顺序被查找
如果对下一个类存在两个合法的选择,选择第一个父类
抽象类
#用于统一化的标准接口,子类必须定义父类定义好的接口
import abc
class Animal(metaclass=abc.ABCMeta): #metaclass=abc.ABCMeta:元类
    @abc.abstractmethod
    def eat(self):
        pass
    @abc.abstractmethod
    def run(self):
        pass
class People(Animal):
    def eat(self):
        print(“pople is eating”)
    def run(self):
        print(“pople is runing”)
a = People()
a.eat()
封装
广义的封装:将一些内容放到一个”容器”中
狭义的封装:私有
class test:
    name = “jim”
    __name = “tom” #私有属性
    def func(self):  #动态方法
        pass
    def __init__(self): #特殊方法
        self.name
        self.__age = age #私有对象属性
    def _func(self): #私有方法
        pass
    @property  #属性:将方法伪装成一个属性,虽然在代码层面没有提升,但是会让代码看起来更合理;
    def func1(self):
        pass
    @classmethod #类方法(用于对于类的修改)
    def func2(cls):  #cls会接收类名类似self接收对象名一样
        pass
    @staticmethod #静态方法:不依赖类与对象的函数,封装在类中用于代码整洁一体化
    def func3():
        pass
私有成员:私有变量 私有对象属性 私有方法
class A:
    count = “china”
    __name = “alex”
    def __init__(self,name,age):
        self.name = name
        self.age = age
    def func(self):
        print(self.__name)
    def __fuck(self):
        pass
obj = A(“jim”, 28)
print(obj.coutry)  # 类外可以访问
print(obj.__name)  # 类外不可以访问
#私有:子类也不可以访问私有属性等 只有类内部可以访问
类方法
必须通过类的调用,而且此方法的意义就是对类里面的变量或者方法进行修改或添加
class c:
    count = 0
    def __init__(self)
        c.cou()
    @classmethod
    def cou(cls):
        cls.count += 1
静态方法
不依赖类及对象的普通函数,在类里面是为了保证代码的一致性
在类外面也可以写一个同样的函数实现功能,但是这样打乱了逻辑关系,也增加了代码的维护难度
主要是为了代码整洁归类
class c:
    def __init__(self):
        pass
    @staticmethod
    def func():
        print(666)
属性
@property:主要让代码看的更合理
class test:
    def __init__(self):
        pass
    @property   #属性
    def aaa(self):
        pass
    @aaa.setter  #.setter修改属性
    def aaa(self,vale):
        print(“测试”,vale)
obj = test()
obj.aaa = 666
isinstanc
:判断obj是否此类或此类的子孙类实例化的对象
print(issubclass(b,a) #True
issubclass:判断B是否是A的子类或孙类
反射:通过字符串操作对象(实例化 类 模块)
hasattr():查找
getattr():获取
setattr():修改
delattr():删除
对实例化对象的示例
class a:
    def __init__(self,name,age):
        self.name = name
        self.age = age
obj = a(“jim”,28)
ret = getattr(obj,”name”,None)
print(ret)
print(hasattr(obj,”name”))
if hasattr(obj,name):
    ret = getattr(obj,”name”,None)
setattr(obj,”sex”,”男”)
print(getattr(obj,”sex”))
对类
class a:
    name = “kom”
    def __init__(self):
        pass
    def func(self):
        print(“in func”)
getattr(a,”name”)
ret = getattr(a,”func”)
print(ret(1))
对当前模块(文件)
import sys
def s1():
    print ‘s1’
def s2():
    print ‘s2’
this_module = sys.modules[__name__]
hasattr(this_module, ‘s1’)
getattr(this_module, ‘s2’)
对其他模块(文件)
import fs
print(getattr(fs,”n1″))
#方法1
a = getattr(fs,”A”)
print(a.name)
#方法2
print(getattr(fs.A,”name”))
a.func2(1)
双下方法
class test:
    def __str__(self):  #__str__方法,那么在打印对象 时默认输出该方法的返回值
        print(666)
    def __repr__(self):  #__repr__方法,那么在repr(对象) 时,默认输出该方法的返回值
        return “太白”
class Foo:
    def __init__(self):
        pass
    def __call__(self, *args, **kwargs): #__call__:对象()自动触发__call__() 方法
    print(“__call__”)
obj = Foo()
obj()  # 对象() 触发__call__() 方法
#__del__:当内存中释放时,自动触发
class test:
    def __init__(self):
        print(“is init”)
    def __new__(cls, *args, **kwargs):  #__new__:对象的产生者
        print(“is new”)
        #super().__new__(cls)
        return object.__new__(cls)
a = test()
#__init__方法:负责对象的初始化,在初始化前对象已经产生
#__new__方法:属于新式类里的方法,第一个参数是(cls),该方法在实例化的时候会自动调用用于创建对象,并将返回值返回给__init__方法的self参数;
class test:
    def __init__(self):
        print(“__init__ “)
        super(test, self).__init__()
    def __new__(cls):
        print(“__new__ “)
        return super(test, cls).__new__(cls)
test()
#输出
__new__
__init__
#从输出结果来看, __new__方法先被调用,返回一个实例对象,接着 __init__ 被调用。 __call__方法并没有被调用;
def __init__(self):
    print(“__init__ “)
    print(self)
    super(A, self).__init__()
def __new__(cls):
    print(“__new__ “)
    self = super(A, cls).__new__(cls)
    print(self)
    return self
#输出
__new__
<__main__.A object at 0x1046c4a20>
__init__
<__main__.A object at 0x1046c4a20>
#从输出结果来看,__new__ 方法的返回值就是类的实例对象,这个实例对象会传递给 __init__ 方法中的self参数,以便实例对象可以被正确地初始化;
#__init__方法中除了self之外定义的参数,都将与__new__方法中除cls参数之外的参数是必须保持一致
class B:
    def __init__(self, *args, **kwargs):
        print(“init”, args, kwargs)
    def __new__(cls, *args, **kwargs):
        print(“new”, args, kwargs)
        return super().__new__(cls)
B(1, 2, 3)
# 输出
new (1, 2, 3) {}
init (1, 2, 3) {}
设计模式
单例模式
由于类产生实例的过程是通过 __new__ 方法来控制的,因此重写该方法来单例模式是非常方便的;
每次初始化都返回同一个实例,所以两次初始化得到的对象的内存地址应该是一样的
class a:
    __instance = None
    def __new__(cls, *args, **kwargs):
        if cls.__instance is None:
            obj = object.__new__(cls)
            cls.__instance = obj
        return cls.__instance
cc = a()
bb = a()
print(cc,bb)
#输出
<__main__.a object at 0x105513898> <__main__.a object at 0x105513898>
item
#对一个对象进行类似字典的操作,就会触发__item__的某个方法
__getitem__
__setitem__
__delitem__

转载请注明:XAMPP中文组官网 » Python-面向对象

您必须 登录 才能发表评论!