python的面向对象编程

python的面向对象编程

类class

标签: Python

#类:类名、属性、方法

类名:狗类
属性:毛发,品种
方法:咬人,看家

定义方法

class Hero(): 经典类定义方法(旧式类,Python2中)
class Hero(object): 新式类定义方法(常用类,Python3中)
object是Python里面所有类的最顶级父类
eg.

class Hero(object):
    #实例方法
    def info(self):
        print("6666")
 #创建实例化对象
a=Hero()
 #调用对象所属类中的方法
a.info()

其中info是一个实例方法,第一个参数一般是self,表示实例对象本身,其作用是一个变量,指向实例对象

#类的属性添加

1.最常见的添加属性的方法 __init__(self,······)对象初始化方法(java中的构造方法)
Python里面提供的 两个下划线开始两个下划线结束的方法就是魔法方法,__init__就是一个魔法方法,如果没写__init__方法,Python会自动创建,但是不会执行任何操作,所以类里面无论是否编写__init__方法,也一定会有__init__

class Person(object):
    # Python给对象添加属性
    #最常见的添加属性的方法 __init__(self,······)对象初始化方法
    def __init__(self,name,age):
        print("对象创建调用这个方法")
        #self.属性  就是对象属性
        self.name = name
        self.age = age
one = Person("张三",18)
 #访问one对象的属性
print(one.name)
print(one.age)

2.实例化后的对象.要添加的属性 表示对象属性
但是该方法可以无限制添加对象,为了规范定义对象的属性,我们尽量不使用该方法

class Person(object):
    pass
one = Person()
 #实例化后的对象.要添加的属性  表示对象属性
one.name = "本杰明"
one.age = 18
print("%s今年%d"%(one.name,one.age))

#查看对象属性

当类中含有__str__魔法方法的时候,打印对象会输出此魔法方法中的返回值,调用此方法时需要用一个变量接受
在类中使用时

def __str__(self):
    return "%s今年%d"%(one.name,one.age)

在类外调用时

word = one.__str__()
print(word)

例如

class Person(object):
    def __init__(self,name,age):
        self.name = name
        self.age = age
    #如果我们不带__str__方法会输出对象的内存地址
    #带__str__方法我们可以定义打印对象返回的数据
    def __str__(self):
        return "{name}今年{age}岁".format(name=self.name,age=self.age)
zhangsan = Person("张三",18)
print(zhangsan)

#del() 方法删除对象

#引用计数法(类似于java的gc线程回收时回收对象的计数法)

class Hero(object):
    def __init__(self,name):
        print("__init__()方法被调用")
        self.name = name

    def __del__(self):
        print("__del__()方法被执行")

a = Hero(“大司马”)
b = a
c = b
建立了一个对象,默认保存在计算机内存中,一旦该对象不被使用(没有变量名引用该对象时),系统将要收回内存资源,对象会自动执行销毁机制__del__()魔法方法
例如,上述的 Hero(“大司马”) 该对象被a、b、c这三个变量名引用了三次,需要将这三个引用删除(del(a) del(b) del©),才能实行销毁机制__del__()
del 销毁创建的变量和变量所对应的数据指数
一旦内存引用为0的时候,解释器会回收当前资源
这种销毁机制叫引用计数法
引用计数法:
1.当有变量保存了一个对象的引用时(内存地址),此对象的引用计数+1
2.当使用 del()方法 或者 del关键字 删除变量指向的对象时,会减小对象的引用计数(如果对象的引用计数不为1,那么该对象的引用计数-1;当对象的引用计数为0时,对象就会被真正删除,内存回收)

#对象方法
所有的对象共用同一个类中定义的实例方法

class Person(object):
    # Python给对象添加属性
    #最常见的添加属性的方法 __init__(self,······)对象初始化方法
    def __init__(self,name,age):
        print("对象创建调用这个方法")
        #self.属性  就是对象属性
        self.name = name
        self.age = age
    #实例化方法
    def run(self):
        print("人类快跑")
    def eat(self):
        print("人类快吃")
    def show_name(self):
        #通过self访问实例化本身
        print("我叫%s"%self.name)
one = Person("张三",18)
 #访问one对象的方法
one.run()
one.eat()
one.show_name()

#注意

在类的内部获取 属性 和 实例方法 通过self获取
在类的外部获取 属性 和 实例方法 通过对象名获取
如果一个类有多个对象,每个对象的属性是各自保存的,都有各自独立地址
但是实例方法是所有对象共享的,只占用一份内存空间,类会通过self来判断是哪个对象调用了实例方法

class Person(object):
    def __init__(self,name,age,height):
        self.name = name
        self.age = age
        self.height = height
    def run(self):
        print("%s在跑"%self.name)
    def show_age(self):
        print("%d岁"%self.age)
    def show_height(self):
        print("%dcm"%self.height)
one = Person("本杰明",18,180)
two = Person("张三",20,175)
print(one.name,id(one.run))
print(two.name,id(two.run))
print(id(one))
print(id(two))

#练习(烤地瓜)

class BakedSweetPotato(object):
    def __init__(self,cookedLevel,cookedString,condiments):
        self.cookedLevel = cookedLevel
        self.cookedString = cookedString
        self.condiments = condiments
    def cook(self):
        print("把地瓜烤一段时间")
        self.cookedLevel+=1
        if 0<=self.cookedLevel<=3:
            self.cookedString="生的"
        elif 3<self.cookedLevel<=5:
            self.cookedString="半生不熟"
        elif 5<self.cookedLevel<=8:
            self.cookedString="熟了"
        elif self.cookedLevel>8:
            self.cookedString="烤成碳了"
    def addCondiments(self):
        print("给地瓜添加配料")
        if self.condiments:
            pass
        else:
            print("没有添加佐料")
        zuoliao = input("请添加佐料")
        self.condiments.append(zuoliao.split(","))
    def __str__(self):
        return "地瓜的烤熟程度为{cookedLevel},{cookedString},添加的佐料有{condiments}".format(cookedLevel=self.cookedLevel,cookedString=self.cookedString,condiments=self.condiments)
one = BakedSweetPotato(0,"生的",[])
print(one)
one.cook()
print(one)
one.addCondiments()
print(one)

#类的继承

eg
Dog: 名字 品种 吃 喝 拉 撒
哈士奇Dog:名字 品种 吃 喝 拉 撒 拆家
金毛Dog:名字 品种 吃 喝 拉 撒 卖萌

程序中的继承:描述的是多个类之间的所属关系
如果一个类A里面的属性和方法可以重复使用,那么可以通过继承的方式传递给B类
例如

class Dog(object):
    def __init__(self,name):
        self.name = name
    def eat(self):
        print("%s在吃狗粮"%self.name)
    def drink(self):
        print("%s在喝水"%self.name)
class HaDog(Dog):
    def chai(self):
        print("%s在拆家"%self.name)
one = HaDog("小天圈")
one.eat()
one.chai()

其中Dog是父类也是基类 HaDog是子类也是衍生类

#单继承

一个类只能继承一个父类
如上HaDog

#多继承

一个子类可以继承多个父类
如果想要将HaDog变为多继承
例如

class Dog(object):
    pass
class JunDog(object):
    pass
class HaDog(Dog,JunDog):
    pass

注意HaDog(Dog,JunDog)中,哪个父类在前,同方法使用第一个父类
前一个继承的类一定要小于后边的类,前面的不能是后面的父级类
即当多个父类中含有同一个方法,使用mro的继承顺序使用第一个继承的父类方法(mro继承顺序:子类继承多个父类的前后顺序,谁在前继承谁)
使用 类名._mro_ 例如:print(HaDog.__mro__) 即可该类的查看mro顺序
遇到继承推算时,使用C3算法,即入度为0的方法推算,即没有指向的类时可以去掉(入度为0,从上到下)

#——————————————

#重写

#——————————————
在子类中重写父类的方法
例如

class Dog(object):
    def __init__(self,name):
        self.name = name
    def eat(self):
        print("%s在吃狗粮"%self.name)
    def drink(self):
        print("%s在喝水"%self.name)
class JunDog(object):
    def zhuaren(self):
        print("%s会抓人"%self.name)
class HaDog(JunDog):
    def zhuaren(self):
        print("%s只会拆家"%self.name)



#重写后,怎么调用父类的同名属性和方法
​ 父类名.方法或属性
​ 使用父类的方法时,方法中要传递实例化对象即self
​ class Master(object):
​ def init(self):
​ self.kongfu = “天津”
​ def make_cake(self):
​ print(“使用%s手法煎饼”%self.kongfu)
​ def make_ice(self):
​ print(“天津冰淇淋”)

class Prentice(Master):
    def __init__(self):
        self.kongfu = "山东"
    def make_cake(self):
        print("使用%s手法煎饼" % self.kongfu)
        #怎么调用父类的同名属性和方法
        #父类名.方法或属性
        #使用父类的方法时,方法中要传递实例化对象即self
        Master.__init__(self)
        print("使用%s手法煎饼" % self.kongfu)
    def make_ice(self):
        print("山东冰淇淋" )
        Master.make_ice(self)

zq = Prentice()
print(zq.kongfu)
zq.make_cake()
zq.make_ice()

#super().父类的属性和方法

super([类名,self]).父类的属性和方法
其中类名默认为当前子类,中括号中可选择自己指定的类,按当前子类的继承顺序,继承该指定类的下一级类

class Master(object):
    def __init__(self):
        self.kongfu = "天津"
    def make_cake(self):
        print("使用%s手法煎饼"%self.kongfu)

class WhTedu(object):
    def __init__(self):
        self.kongfu = "武汉"
    def make_cake(self):
        print("使用%s手法煎饼"%self.kongfu)

class Prentice(Master,WhTedu):
    def __init__(self):
        self.kongfu = "山东"
    def make_cake(self):
        print("使用%s手法煎饼" % self.kongfu)
        #怎么调用父类的同名属性和方法
        #父类名.方法或属性
        #使用父类的方法时,方法中要传递实例化对象即self
        super().__init__()
        print("使用%s手法煎饼" % self.kongfu)
        super(Master,self).__init__()
        print("使用%s手法煎饼" % self.kongfu)

zq = Prentice()
print(zq.kongfu)
zq.make_cake()

如果继承了多个父类,且父类都含有 同名 属性或者方法,使用super方法,默认执行第一个父类的同名属性或者方法
super()方法只支持新式类,Python2.3之后才有的多层继承和super()方法
调用时遵循类的继承顺序(mro顺序)

#私有权限

在 属性名 或者 方法名 的 前面 加上两个下划线
python是一个弱语言 没有绝对的访问权限,必须遵守Python的定义
私有属性的原则,Python没有访问控制符(public)
“”"
1.类的私有属性和私有方法,都不能通过对象直接访问,但是可以通过本类的内部进行访问
2.类的私有属性和私有方法,都不能被子类继承,也不能被子类访问
3.类的私有属性和私有方法,往往用来处理类的内部事情,不能通过对象处理起到安全作用
“”"

如果属性名和方法名前面没有两个下划线的话是 公有权限(不太准确 )
python中没有绝对的公有访问和私有访问
“”"
1.当使用 import 模块名 可以使用所有属性和方法,无公有私有说法
2.当使用 form 模块名 import 方法或属性 时,有公有和私有,且有特殊情况(一个下划线即可表示私有),所以定义私有属性时,必须遵循业界规范使用二个下划线
“”"

class yxt(object):
    def __init__(self):
        self.__money = 10000
        self.kongfu = "啥都6"
    def jie_money(self):
        print("爸爸向儿子借了%d" %self.__money)
    def __play(self):
        print("全英雄全能6的飞起")

class zq(yxt):
    pass

hh = zq()
hh.jie_money()

_dict_ 魔法方法:
1.类属性调用此魔法方法时,返回当前类所含有的所有类属性和方法
2.实例化对象调用此魔法方法时,返回此对象具有的所有属性
通过该方法我们可以发现Python中私有属性的秘密
私有属性被修改了名字,外部访问时格式为 _类名__私有属性名
例如

class A(object):
    name = "A类"
    __data = "2019"
    def __init__(self):
        self.age = 18
        self.__money = 1000
print(A.__dict__)
print (A._A__data)
a = A()
print(a.__dict__)
print(a._A__money)

所以访问私有属性的方法可以为在该私有属性前面加上 _类名
即以 _类名__属性名 该格式访问私有属性
因此,Python中的私有属性是假的私有(伪私有属性):Python的类通过加双下划线来设置“私有属性”,原理是Python解释器将加了双下划线的“属性名”自动转换成“_类名__私有属性名”,所以外部访问该属性时获取不到,会触发AttributeError,从而实现Python的私有属性
(访问私有方法相同)

#怎么修改对象的属性和方法

“”"
1.外部对象名.属性名 = 新的数据 (直接修改)
2.内部self.属性名 = 新的数据 (直接修改)
3.对象名或者self.方法名 此方法名必须公有(间接修改)
“”"

class Master(object):
    def __init__(self):
        self.__money = 10000
        self.kongfu = "啥都6"
    #业界规范:通常定义get_xxx()方法和set_xxx()方法来获取和修改私有属性,其中xxx指私有属性
    def get_money(self):
        print(self.__money)
    def set_money(self,count):
        self.__money += count

ds = Master()
ds.get_money()
ds.set_money(10000)
ds.get_money()

#类属性和实例属性

“”"
1.实例属性:对象属性,一般定义在__init__() 方法里
不能被类对象调用,能被实例化对象调用
2.类属性
类属性就是类对象都拥有的属性,它被所有类对象和实例对象共有。
类对象:实例化对象 类本身也是对象
直接在类中创建,不能在方法中创建
可以被类对象和实例化对象使用
“”"

class People(object):
    # 在类里面直接定义
    name = "于谦"
    def __init__(self):
        self.age = 18
        # 局部变量
        height = 100

p = People()
 # p实例化对象
print(p.name)
print(People.name)
print(p.age)
 # print(p.height)
 # print(People.age)
 # print(People.height)

class A(object):
    pass
print(type(A))
print(id(A))

#额外知识

type类是元类,所有类的父类 ==》object

python中的元类实例化所有创建出来的类

#类方法是类对象拥有的方法,需要使用装饰器@classmethod 来标识其为类方法,
对于类方法,第一个参数必须是类对象,一般为 cls 作为第一个参数,能通过类对象和实例化对象来调用
类方法的作用:用来访问和修改定义的类属性

class People(object):
    __country = "China"
    #类方法通过classmethod
    def __init__(self):
        name = "yxt"
    @classmethod
    def get_country(cls):
        #cls同self一样
        # print(id(cls))
        # print(cls.__country)
        return cls.__country
    @classmethod
    def set_country(cls,country):
        cls.__country = country
    def set_name(self,name):
        self.name = name
print(id(People))
People.get_country()
a = People()
country = a.get_country()
a.set_country("usa")
print(a.get_country())
a.set_name("zq")
print(a.name)
b = People()
print(b.get_country())

#Python是一门弱语言,面向对象,面向过程

“”"
1.没有访问控制符
2.没有常量 Python中的常量的定义方法:通过把变量名全部大写来定义(可以被修改,规定不要修改)
3.定义变量不需要指定数据类型
4.面向对象没有多态说法
5.没有绝对私有
“”"
#Python中没有静态方法,对于Python中的类假写了一个静态方法
需要通过装饰器 @staticmethod 来修饰,静态方法不需要定义参数,可以通过类对象和实例化对象来访问
作用:为了符合高级语言特意定义的,无实际意义
可以不需要实例化对象直接通过类对象使用
静态方法如果使用类属性和对象属性
使用类属性:类名.属性(不用来访问私有属性)
使用对象属性:需要通过传参(参数为实例化对象),来间接访问

class People(object):
    name = "剑豪"
    __job = "中单"
    def __init__(self):
        self.age = "18"
    @staticmethod
    def show():
        print(People.name)
        print(People.__job)
    @staticmethod
    def show_age(obj):
        print(obj.age)
    #绝对不要用下面这个静态方法,因为该方法是我们先创建了一个实例化对象后才写的
    #所有语言中 类的方法的功能必须在实例化对象之前定义完成
    @staticmethod
    def show_age1():
        print(a.age)
People.show()
a = People()
print(a.age)
a.show()
a.show_age(a)
a.show_age1()

#所有高级语言都具有的特点:面向对象
#面向对象的三大特征:封装、继承、多态
#封装的意义:
“”"
1.将属性和方法放到一起作为一个整体(类),然后通过实例对象来处理
2.隐藏内部的实现细节(通过加添私有属性),只需要对象及其属性和方法在内部交互(使方法在类的内部启动,即实例化对象时就自动执行)
3.对于类的属性和方法需要增加访问控制
“”"

#多态
所谓多态就是定义时的类型和运行时的类型不一样,此时为多态,即同一个事物的不同表现形态
多态的概念经常用于强语言类型(Java/C#)
多态的触发条件
“”"
1.继承关系
2.重写
3.父类引用指向子类对象(向上造型)
“”"
#在Python中弱化了多态,无真正的多态,因为Python是一门弱语言,没有指向类型即不需要指定数据类型(int,char,类名等),无法向上造型

class Animal(object):
    def eat(self):
        print("动物吃")
class cat(Animal):
    def eat(self):
        print("猫吃鱼")
class Dog(Animal):
    def eat(self):
        print("狗吃屎")
class Pig(object):
    def eat(self):
        print("猪吃糠")
 #在Python中使用多态
def show_eat(obj):
    obj.eat()
show_eat(Dog())
 #在Java中下面无法实现,因为Pig不属于Animal
show_eat(Pig())
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值