(八)面向对象

(一)

1.1 面向对象的定义

  1. 通常类中的方法都有一个self参数,除过self参数,不用考虑,其他传递的参数都需要考虑
  2. 适用于函数特多,将函数进行划分归类的情况【封装】
  3. 注意:类名要大写,方法(函数)要有self参数
class 类名:
	def 方法名(self,*args):
		print(*args)
		return 123

obj = 类名()
res = obj.方法名(‘run’)
print(res)
#函数
def func1():
    pass


#类
class Account():
    #方法
    def func1(self):
        pass

1.2 类的调用

  1. 先创建一个对象
  2. 通过使用对象,调用类中的方法
#类
class Account():
    #方法
    def func1(self):
        print('func1')
        return 123

#创建一个Account对象
x = Account()
res = x.func1()
print(res)

1.3 对象的作用【封装】

存储一些值,方便以后自己使用
每创建一个对象,都会为这些对象重新开辟一块新的内存空间,在对象中封装【独有的性质】,方便以后调用

class File():
    #方法
    def read(self):
        print('read'   )
        with open(self.path , mode='r',encoding='utf-8') as f:
            data = f.read()
        return data

    def write(self,content,path):
        with open(self.path , mode='w',encoding='utf-8') as f:
            data = f.write(content)


#创建一个File对象
obj1  = File()
#在对象中写了一个path = 'user.txt'
obj1.path = 'user.txt'

#self是哪个对象调用方法,self就是谁
#通过对象调用类中的read方法,read方法中的self就是obj
#每创建一个对象,都会为这些对象重新开辟一块新的内存空间,在对象中封装【独有的性质】,方便以后调用
obj1.read()

class  Person():
    def show(self):
        str1 = '性别:{n1},年龄:{n2}'.format(n1 = self.gender , n2 = self.age)
        print(str1)
        print(self.age)


p1 = Person()
p1.age = 18
p1.name = 'run'
p1.gender = 'woman'
p1.show()

p2 = Person()
p2.age = 38
p2.name = 'jie'
p2.gender = 'man'
p2.show()

为了能够方便再函数中封装多个数据,可以在函数中写一个__init__方法,类()实例化一个对象,自动执行__init__方法(初始化方法/构造方法)

class  Person():
    def __init__(self,name,age,gender):
        print('执行init方法')
        self.name = name
        self.age = age
        self.gender = gender
    def show(self):
        str1 = '性别:{n1},年龄:{n2}'.format(n1 = self.gender , n2 = self.age)
        print(str1)
        

#类()实例化一个对象,自动执行__init__方法
p1 = Person(name='run',age = 18,gender='woman')
p1.show()

总结:如果写代码时,函数比较多比较乱

  1. 可以将函数归类并放到同一个类中
  2. 函数如果有反复使用的公共值,则可以放到对象中
  3. 将数据封装到对象,方便调用

谈谈您印象中的封装?

  1. 将同一类的方法封装在一起
  2. 将数据封装到对象中,方便以后调用

面向对象的小示例【游戏】

class Police():
    def __init__(self,name):
        self.name = name
        self.hp =1000

    def knive(self,other):
        msg = '{}砍了{}一刀'.format(self.name,other.name)
        print(msg)
        self.hp -= 100
        other.hp -= 400
    def fight(self,other):
        msg = '{}去打仗了'.format(self.name,other.name)
        print(msg)
        self.hp += 100
        other.hp -= 400


class Bandit():
    def __init__(self,name):
        self.name = name
        self.hp = 1000

    def murder(self,murdername):
        msg = '{}去谋杀了{}'.format(self.name,murdername.name)
        self.hp -=10
        murdername.hp -=20
        print(msg)

p3 = Police('jie')
b1 = Bandit('jun')
p3.knive(b1)
p3.fight(b1)
b1.murder(p3)
print(b1.hp,p3.hp)

1.4 继承

#父类  (基类)
class Base():
    def f1(self):
        pass

#子类  (派生类)
class Foo(Base):
    def f2(self):
        pass

#创建一个子类对象

chil = Foo()

#执行对象,方法时,有现在自己找,如果没有就从父类找
chil.f2()
chil.f1()

fath = Base()
fath.f1()
# fath.f2()  #报错

什么时候才能用到继承?
答:多个类中如果有公共的方法,可以放到基类中,避免代码的重复编写

注:
继承关系中的查找循序
1.找清楚self到底是谁:self是哪个类创建的,就从此类开始找,自己没有找父类。

# 示例一 
class Base():
    def f1(self):
        print('base.f1')


class Foo(Base):
    def f2(self):
        print('foo.f2')

chil = Foo()
chil.f1()
chil.f2()


'''
base.f1   self是chil
foo.f2
'''
#示例二
class Base():
    def f1(self):
        print('base.f1')


class Foo(Base):
    def f2(self):
        self.f1()   #self 是chil
        print('foo.f2')

chil = Foo()
chil.f1()
chil.f2()


'''
base.f1   执行chil.f1()所得
base.f1   执行chil.f2()所得,在执行f2函数的时候,由于Foo中没有f1函数,所以只能去父类中找
foo.f2
'''


# 示例三
class Base():
    def f1(self):
        print('base.f1')


class Foo(Base):
    def f2(self):
        self.f1()
        print('foo.f2')

    def f1(self):
        print('foo.f1')

chil = Foo()
chil.f1()
chil.f2()

'''
foo.f1  优先去自己这里找
foo.f1
foo.f2
'''

#示例四
class Base():
    def f1(self):
        self.f2()
        print('base.f1')

    def f2(self):
        print('base.f2')


class Foo(Base):
    def f2(self):
        print('foo.f2')


chil = Foo()   #self是Foo对象,先从自己找
chil.f1()


'''
foo.f2
base.f1
'''

1.5 多态(多种形态/多种类型)【鸭子模型】

面试题:什么是鸭子模型?
对于一个函数而言,python对于参数的类型不会限制,传入参数时可以是各种类型,在函数中有例如:arg.send方法,那么就是对于传入类型的一个限制(类型必须有send方法)。
这就是鸭子模型,类似于上述的函数,我们认为只要能呱呱叫的就是鸭子(只有有send方法,就是我们想要的类型)

# arg是多种类型的,若list,str,tuple等都可以
def fun(arg):
    v = arg[-1]
    print(v)

def func(arg):
	arg.send()  #必须具有send方法呱呱叫

什么时候用面向对象 ?

  1. 函数(业务功能)比较多,可以通过面向对象来归类。
  2. 想要做数据封装(创建字典存储数据,面向对象)
  3. 游戏示例:创建一些角色,并根据角色创建人物

(二)

2.1 类成员

类成员

  • 类变量(静态字段/属性)
  • 方法

对象成员

  • 实例变量(字段/属性)

class Foo:
    def __init__(self,name):
        self.name = name
    def show(self):
        print(self.name)

# Foo申明一个对象,Foo()开始执行__init__方法
obj1 = Foo('run')
obj2 = Foo('jie')

在这里插入图片描述

2.2 类变量
class Foo:
    city = 'beijing '

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

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

obj1 = Foo('run')
obj1.show()
print(obj1.city)   
print(Foo.city)
obj2 = Foo('jie')
obj2.show()
print(obj2.city)

定义:写在类的下一级和方法同一级。如上,city即为类变量

访问:

类.类变量名称
对象.类变量名称

面试题

class Base:
    x = 1

obj = Base()
print(obj.x)
obj.y = 123  #在对象中添加一个 y = 123的变量
print(obj.y)
obj.x = 123  #在对象中添加一个 x = 123的变量
print(obj.x)  #先在对象中找,对象中没有去类中找
Base.x = 444  #将Base 中的x的值改为444
print(Base.x)


'''
1
123
123
444
'''
class Parent:
    x = 1
class child(Parent):
    pass
class child2(Parent):
    pass

print(Parent.x , child.x,child2.x)  # 1 1 1
child2.x = 66
print(Parent.x , child.x,child2.x)  #1 1 66
child.x = 333
print(Parent.x , child.x,child2.x)   #1 333 66

  1. 对于对象,在引用值的时候,先找自己,自己没有所属类,所属类没有找该类的基类
  2. 在修改/赋值的时候,只能修改该对象自己的值,不能修改类变量的值
2.3 方法(绑定方法)
  • 定义:至少有一个self参数
  • 执行:先创建对象,由对象.方法(只能通过对象调用)
  • 用途:用于需要用到方法中的值得时候
2.4 静态方法

定义:

  • @staticmethod装饰器
  • 参数无限制

执行 :

  • 类.静态方法名
  • 对象.静态方法名(不推荐)
class Foo():
    def __init__(self,name):
        self.name = name

    def func(self,a,b):
        print(self.name,a,b)

# 定义的时候,对参数没有限制
    @staticmethod
    def func1():
        print(123)


obj = Foo('run')
obj.func(123,56)

# 这个不用创建对象在调用函数,他通过类名.方法名就可以
Foo.func1()
2.5 类方法

定义:

  • @classmethod装饰器
  • 至少有cls参数,当前类

执行

  • 类.类方法
  • 对象.类方法(不推荐)
  • 面试题:@classmethod 与@ staticmechod方法的区别。
  • 一个是类方法一个是静态方法
  • 定义:
    类方法:用cassmethod做装饰器且至少有一个cls参数
    静态方法:用staticmethod做装饰器且参数无限制
  • 调用:
    类.方法直接调用
    对象. 方法直接调用
2.6 属性

定义:

  • @property装饰器
  • 只有self参数

执行

  • 对象.方法(不推荐)
    调用的时候,通过对象.方法 (不加括号)
class Foo:
    def func1(self):
        print(123)
        return 666

    @property
    def func2(self):
        print(789)
        return 666

f1 = Foo()
res1 = f1.func1()
print(res1)

# 属性:
# 方法前装饰器用  @property
# 调用的时候,通过对象.方法  (不加括号)
f2 = Foo()
res2 = f2.func2
print(res2)
2.7 成员修饰符(公共/私有 变量/方法)

只要在方法或者变量名称前边加上 __,则其就会变成私有,私有变量只有内部可以访问,外部无法访问,其基类也无法访问。

class Foo():
    def __init__(self,name,age):
        self.name = name  #公共变量
        self.__age = age  #私有变量,外部无法访问得到

    def func(self):
        print(self.name)

    def func2(self):
        print(self.__age)

obj = Foo('alex','13')
obj.func()
print(obj.name)   #可以访问
obj.func2()     #内部可以访问
# print(obj.__age)   #无法访问(报错)

class Foo:
    __x = 1

    @staticmethod
    def func():
        print(Foo.__x)
obj = Foo()
obj.func()
# print(Foo.__x)    #无法访问,报错
print(Foo._Foo__x)    #强制访问
class Foo:
    def func(self):
        print('msg1')

    def __func2(self):
        print('msg2')

    def show(self):
        print('show')
        self.func()
        self.__func2()
obj = Foo()
obj.func()
obj.show()
# obj.__func2()   #报错
class Base():
    def __func(self):
        print('base')


class Foo(Base):
    def func(self):
        print('msg1')
        self.__func()  #报错

obj = Foo()
# obj.__func()  #报错
obj.func()

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值