面向对象一些基础内容

1. 初识面向对象

1.1核心概念

  • 对象
  • self

想要通过面向对象去实现某个或某些功能时需要2步:

  • 定义类,在类中定义方法,在方法中去实现具体的功能。

  • 实例化类并的个一个对象,通过对象去调用并执行方法。

    例如:

    class Message:
        
        def send_email(self, email, content):
          data = "给{}发邮件,内容是:{}".format(email, content)
          print(data)
      
    msg_object = Message() # 实例化一个对象 msg_object,创建了一个一块区域。
    msg_object.send_email("xxx@qq.com","注册成功")
    

注意:1.类名称首字母大写&驼峰式命名;2.py3之后默认类都继承object;3.在类种编写的函数称为方法;4.每个方法的第一个参数是self。

1.1 对象和self

在每个类中都可以定义个特殊的:__init__ 初始化方法,在实例化类创建对象时自动执行,即:对象=类()

class Message:

    def __init__(self, content):
        self.data = content

    def send_email(self, email):
        data = "给{}发邮件,内容是:{}".format(email, self.data)
        print(data)
# 对象 = 类名() # 自动执行类中的 __init__ 方法。

# 1. 根据类型创建一个对象,内存的一块 区域 。
# 2. 执行__init__方法,模块会将创建的那块区域的内存地址当self参数传递进去。
  • 对象,让我们可以在它的内部先封装一部分数据,以后想要使用时,再去里面获取。
  • self,类中的方法需要由这个类的对象来触发并执行( 对象.方法名 ),且在执行时会自动将对象当做参数传递给self,以供方法中获取对象中已封装的值。

注意:除了self默认参数以外,方法中的参数的定义和执行与函数是相同。

面向对象的思想:将一些数据封装到对象中,在执行方法时,再去对象中获取。

函数式的思想:函数内部需要的数据均通过参数的形式传递。

  • self,本质上就是一个参数。这个参数是Python内部会提供,其实本质上就是调用当前方法的那个对象。
  • 对象,基于类实例化出来”一块内存“,默认里面没有数据;经过类的 __init__方法,可以在内存中初始化一些数据。

1.2 常见成员

在编写面向对象相关代码时,最常见成员有:

  • 实例变量,属于对象,只能通过对象调用。
  • 绑定方法,属于类,通过对象调用 或 通过类调用
class Person:

    def __init__(self, n1, n2):
        # 实例变量
        self.name = n1
        self.age = n2
     
     # 绑定方法
     def show(self):
         msg = "我叫{},今年{}岁。".format(self.name, self.age)
         print(msg)
# 执行绑定方法
p1 = Person("xxx",22)
p1.show()
# 或
# p1 = Person("xxx",22)
# Person.show(p1)

1.3 其他成员

  • 变量
    • 实例变量
    • 类变量
  • 方法
    • 绑定方法
    • 类方法
    • 静态方法
  • 属性

1.3.1 变量

  • 实例变量,属于对象,每个对象中各自维护自己的数据。
  • 类变量,属于类,可以被所有对象共享,一般用于给对象提供公共数据(类似于全局变量)。
  1. 当把每个对象中都存在的相同的示例变量时,可以选择把它放在类变量中,这样就可以避免对象中维护多个相同数据。
  2. 注意读和写的区别。
  3. 继承关系中的读写
class Parent(object):
    x = 1

class Child1(Parent):
    pass

class Child2(Parent):
    pass

print(Parent.x, Child1.x, Child2.x) # 1 1 1

Child1.x = 2
print(PParent.x, Child1.x, Child2.x) # 1 2 1

Parent.x = 3
print(Parent.x, Child1.x, Child2.x) # 3 2 3
#建立在Child1.x = 2的基础上

1.3.2 方法

  • 绑定方法,默认有一个self参数,由对象进行调用(此时self就等于调用方法的这个对象)【对象&类均可调用】
  • 类方法,默认有一个cls参数,用类或对象都可以调用(此时cls就等于调用方法的这个类)【对象&类均可调用】
  • 静态方法,无默认参数,用类和对象都可以调用。【对象&类均可调用】
class Foo(object):

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

    def f1(self):
        print("绑定方法", self.name)

    @classmethod
    def f2(cls):
        print("类方法", cls)

    @staticmethod
    def f3():
        print("静态方法")
        
# 绑定方法(对象)
obj = Foo("xxx",20)
obj.f1() # Foo.f1(obj)


# 类方法
Foo.f2()  # cls就是当前调用这个方法的类。(类)
obj.f2()  # cls就是当前调用这个方法的对象的类。


# 静态方法
Foo.f3()  # 类执行执行方法(类)
obj.f3()  # 对象执行执行方法

在类中 @classmethod 和 @staticmethod 的作用?

在类中如果通过@classmethod 或@staticmethod 装饰上这个方法之后,就分别变成了类方法和静态方法,类方法默认有一个cls参数,而静态方法是没有参数的,这两种方法什么时候使用,取决于方法内部实现的功能,如果用到cls就使用@classmethod,否则就使用静态方法。

1.4 属性

属性其实是由绑定方法 + 特殊装饰器 组合创造出来的,以后在调用方法时可以不加括号

关于属性的编写有两种方式:

  • 方式一,基于装饰器
  • 方式二,基于定义变量

由于属性和实例变量的调用方式相同,所以在编写时需要注意:属性名称 不要 实例变量 重名。

如果真的想要在名称上创建一些关系,可以让实例变量加上一个下划线。

1.5 成员修饰符

Python中成员的修饰符就是指的是:公有、私有。

  • 公有,在任何地方都可以调用这个成员。
  • 私有,只有在类的内部才可以调用改成员(成员是以两个下划线开头,则表示该成员为私有)。
class Base(object):

    def __data(self):
        print("base.__data")

    def num(self):
        print("base.num")
        self.__data()  # 不允许执行父类中的私有方法


class Foo(Base):

    def func(self):
        self.num()


obj = Foo()
obj.func()

父类中的私有成员,子类无法继承。

按理说私有成员是无法被外部调用,但如果用一些特殊的语法也可以

1.6特殊成员

在Python的类中存在一些特殊的方法,这些方法都是 __方法__ 格式,这种方法在内部均有特殊的含义,接下来我们来讲一些常见的特殊成员:

  • __init__,初始化方法
  • __new__,构造方法
  • __call__
  • __str__
  • __dict__
  • __enter____exit__
  • __add__ 等。

2. 三大特性

面向对象编程在很多语言中都存在,这种编程方式有三大特性:封装、继承、多态。

2.1 封装

封装主要体现在两个方面:

  • 将同一类方法封装到了一个类中,
  • 将数据封装到了对象中,在实例化一个对象时,可以通过__init__初始化方法在对象中封装一些数据,便于以后使用。
  1. 将数据封装到一个对象,便于以后使用。
class UserInfo:
    def __init__(self, name, pwd, age):
        self.name = name
        self.password = pwd
        self.age = age


def run():
    user_object_list = []
    # 用户注册
    while True:
        user = input("用户名:")
        if user.upper() == "Q":
            break
        pwd = input("密码")

        # user_object对象中有:name/password
        user_object = UserInfo(user, pwd, 19)
        # user_dict = {"name":user,"password":pwd}

        user_object_list.append(user_object)
    # user_object_list.append(user_dict)

    # 展示用户信息
    for obj in user_object_list:
        print(obj.name, obj.password)
 
  总结:
   	- 数据封装到对象,以后再去获取。
       - 规范数据(约束)
  1. 将数据分装到对象中,在方法中对原始数据进行加工处理。
   user_list = ["用户-{}".format(i) for i in range(1,3000)]
   
   # 分页显示,每页显示10条
   while True:
       page = int(input("请输入页码:"))
   
       start_index = (page - 1) * 10
       end_index = page * 10
   
       page_data_list = user_list[start_index:end_index]
       for item in page_data_list:
           print(item)
class Pagination:
       def __init__(self, current_page, per_page_num=10):
           self.per_page_num = per_page_num
           
           if not current_page.isdecimal():
               self.current_page = 1
               return
           current_page = int(current_page)
           if current_page < 1:
               self.current_page = 1
               return
           self.current_page = current_page
   
       def start(self):
           return (self.current_page - 1) * self.per_page_num
   
       def end(self):
            
             return self.current_page * self.per_page_num
   
   
   user_list = ["用户-{}".format(i) for i in range(1, 3000)]
   
   # 分页显示,每页显示10条
   while True:
       page = input("请输入页码:")
   	
       # page,当前访问的页码
       # 10,每页显示10条数据
   	# 内部执行Pagination类的init方法。
       pg_object = Pagination(page, 20)
       page_data_list = user_list[ pg_object.start() : pg_object.end() ]
       #切片
       for item in page_data_list:
           print(item)
  1. 根据类创建多个对象,在方法中对对象中的数据进行修改。
pass
  • 仅做数据封装。
  • 封装数据 + 方法再对数据进行加工处理。
  • 创建同一类的数据且同类数据可以具有相同的功能(方法)。

2.2 继承

传统的理念中有:儿子可以继承父亲的财产。

在面向对象中也有这样的理念,即:子类可以继承父类中的方法和类变量(不是拷贝一份,父类的还是属于父类,子类可以继承而已)。

父类
子类

基类
派生类
class Base:

    def func(self):
        print("Base.func")

class Son(Base):
    
    def show(self):
        print("Son.show")
        
s1 = Son()
s1.show()
s1.func() # 优先在自己的类中找,自己没有才去父类。

s2 = Base()
s2.func()
  • 执行对象.方法时,优先去当前对象所关联的类中找,没有的话才去她的父类中查找。
  • Python支持多继承:先继承左边、再继承右边的。
  • self到底是谁?去self对应的那个类中去获取成员,没有就按照继承关系向上查找 。

2.2.1mro和c3算法

如果类中存在继承关系,在可以通过mro()获取当前类的继承关系(找成员的顺序)。

class C(object):
    pass

class B(object):
    pass

class A(B, C):
    pass

print( A.mro() )   # [<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class 'object'>]
print( A.__mro__ ) # (<class '__main__.A'>, <class '__main__.B'>, <class '__main__.C'>, <class 'object'>)

一句话搞定
从左到右,深度优先,大小钻石,留住顶端

2.3 多态

多态,按字面翻译其实就是多种形态。
Python对数据类型没有任何限制,所以他天生支持多态。

def func(arg):
    v1 = arg.copy() # 浅拷贝
    print(v1)
#传递的字符串,v1就算字符串,传递的列表,
func("name")
func([11,22,33,44])

Python默认支持多态(这种方式称之为鸭子类型)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值