面向对象的进阶

      在《面向对象初级篇》中是对面向对象的基本认识:

         ●面向对象是一种编程方式,此编程方式是基于对 对象 的使用

         ●类 是一个模板,模板中包装了多个 "函数" 以供使用.

         ●对象 ,根据模块创建的实例 , 实例用于调用被包装在类中的函数

         ●面向对象的三大特性 : 封装 , 继承 , 多态 .

       注意:将相关功能封装到类中------将相关数据封装到对象中

 

                            类                           

   类的成员可以分成三大类: 字段 ,方法 , 属性

   注意: 所有成员中,只有普通字段的内容保存对象中,即 : 根据此类创建了多少对象,在内存就有多少个普通字段.而其他的成员,则都是保存在类中,即 : 无论对象的多少,在内存中只创建一份.

      一 . 字段           

  字段分为 : 普通字段(实例变量) 和 静态字段(类变量).

           ●普通字段属于----对象

           ●静态字段属于---

class Foo:
    #类变量(静态字段)
    country = "东北"

    def __init__(self,place):
        #实例变量(普通字段)
        self.place = place

    def func(self):
        print("123")
#直接访问普通字段
obj = Foo("海南")
print(obj.place)
obj.func()
#直接访问静态字段
print(Foo.country)   #obj.country

       准则: 实例变量(普通字段)访问时,使用 对象 访问.即 : obj.place

                 类变量(静态字段)访问时,使用 方法(也可以使用对象访问,但是尽量不用对象访问),即 : Foo.country

  #易错点
class Foo:

    country = "东北"

    def __init__(self,place):
        self.place = place
    
    def func(self):
        pass

obj1 = Foo("海南")
obj2 = Foo("重庆")
print(obj1.place)     #海南
print(obj2.place)     #重庆
print(Foo.country)   #东北

####练习1.
obj1.place = "云南"
print(obj1.place)    #云南
print(obj2.place)    #重庆

####练习2.
obj1.country = "广西"
print(obj1.country)     #广西
print(obj2.country)     #东北

####练习3.
Foo.country = "上海"
print(obj1.country)     #上海
print(obj2.country)     #上海
易错点

      什么时候使用类变量呢:

                当所有对象中有共同的字段时且要同时修改或删除的时候,可以讲 实例变量(普通字段) 提取到 类变量(静态字段).

       二 . 方法               

   方法分为 : 普通方法 , 静态方法 , 类方法 . 三中方法在 内存中都归属于类 ,区别在于调用方式不同.

             ●普通方法 : 有 对象 调用:至少一个 self 参数,执行普通方法时,自动将调用该方法的对象赋值给self

             ●静态方法 : 由 调用, 无默认参数

             ●类方法 : 有 调用 ,至少一个 cls 参数,执行方法时,自动将调用该方法的赋值给cls.

#方法的定义和使用

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


    def func(self):       #无需写方法
        print("func")

    def func1(self):      #定义普通方法,至少有一个 self 参数
        print(self.name)

    @staticmethod        #静态方法,无默认参数.无需使用对象中封装的值
    def func3(a1,a2):
        return a1 + a2

    @classmethod         #类方法,至少有一个 cls 参数
    def func4(cls,x1,x2):
        print(cls,x1,x2)

obj = Foo(123)
obj.func()

#调用普通方法
obj = Foo("张三")
obj.func1()

#调用静态方法
print(Foo.func3(1,2))

#调用类方法
Foo.func4(1,2)

        总结:

                 1.静态方法: 编写时------方法上面写@staticmethod    方法参数可有可无

                                     调用时------类.方法名()       对象.方法名()---(尽量不用这个)

                                     什么时候写静态方法-----无需调用对象中已封装的值.

                 2.类方法:     编写时------方法上面写@classmethod    方法至少有一个 cls 参数

                                     调用时------类名.方法名()    #默认会将当前类传到参数中.

                                     什么时候使用------如果在方法中会使用到当前类,.

123
静态方法/类方法和实例方法的区别?

      三 . 属性                

   属性其实就是通过 普通方法 改造出来的.

#原面向对象方法和属性的对比

class Foo:
    def __init__(self):
        pass
    def func(self):
        return 10
    def func1(self):
        return 20

obj = Foo()
print(obj.func())
print(obj.func1())


##############属性##############
class Foo:
    def __init__(self):
        pass
    @property            #属性定义
    def func(self):
        return 10

    @property
    def func1(self):
        return 20

obj = Foo()              #调用属性
print(obj.func)
print(obj.func1)

                总结:

                       ●编写时 : 在普通方法的基础上加上 @property

                       ●只有一个参数 self

                       ●调用时,无需 括号

                                     方法: obj.func()

                                     属性: obj.func

                       ●应用场景 : 对于简单的方法,当无需传参且有返回值时,可以使用属性

实例:对于主机列表页面,每次请求不可能把数据库中的所有内容都显示到页面上,而是通过分页的功能局部显示,所以在向数据库中请求数据时就要显示的指定获取从第m条到第n条的所有数据(即:limit m,n),这个分页的功能包括:

根据用户请求的当前页和总数据条数计算出 m 和 n
根据m 和 n 去数据库中请求数据 


class Pagenation(object):
    """
    处理分页相关的代码
    """

    def __init__(self,data_list,page,per_page_num=10):
        """
        初始化
        :param data_list: 所有的数据
        :param page: 当前要查看的页面
        :param per_page_num: 每页默认要显示的数据行数
        """
        self.data_list = data_list
        self.page = page
        self.per_page_num = per_page_num

    @property
    def start(self):
        """
        计算索引的起始位置
        :return:
        """
        return (self.page-1) * self.per_page_num

    @property
    def end(self):
        """
        计算索引的结束位置
        :return:
        """
        return self.page * self.per_page_num

    def show(self):
        result = self.data_list[self.start:self.end]
        for row in result:
            print(row)


data_list = []

for i in range(1, 901):
    data_list.append('alex-%s' % i)

while True:
    # 1. 要查看的页面
    page = int(input('请输入要查看的页码:'))
    obj = Pagenation(data_list,page)
    obj.show()
实例

      四 . 类成员的修饰器         

  类 的成员可以分成 3 类 6个,对于每一个成员而言都有两种形式.

                   ●  公有成员 , 在任何地方都能访问

                   ●  私有成员 , 只有在类的内部才能访问

私有成员和公有成员的定义不同:私有成员命名时,前两个字符是下划线.(特殊成员除外,__init__).

私有成员和公有成员的访问限制不同:

   静态字段

               公有静态字段 : 类可以访问,类内部可以访问,派生类(子类)可以访问

             ●  私有静态字段 : 仅类内部可以访问

class C:

    name = "公有静态字段"

    def func(self):
        print C.name

class D(C):

    def show(self):
        print C.name


C.name         # 类访问

obj = C()
obj.func()     # 类内部可以访问

obj_son = D()
obj_son.show() # 派生类中可以访问
公有静态字段
class C:

    __name = "公有静态字段"

    def func(self):
        print C.__name

class D(C):

    def show(self):
        print C.__name


C.__name       # 类访问            ==> 错误

obj = C()
obj.func()     # 类内部可以访问     ==> 正确

obj_son = D()
obj_son.show() # 派生类中可以访问   ==> 错误
私有静态字段

   普通字段

              ● 公有普通字段 : 对象可以访问,类内部可以访问,派生类可以访问

              ● 私有普通字段,仅类内部可以访问

ps: 如果想要强制访问私有字段 ,可以通过  对象._类名__私有字段名    不建议使用

class C:
    
    def __init__(self):
        self.foo = "公有字段"

    def func(self):
        print self.foo  # 类内部访问

class D(C):
    
    def show(self):
        print self.foo # 派生类中访问

obj = C()

obj.foo     # 通过对象访问
obj.func()  # 类内部访问

obj_son = D();
obj_son.show()  # 派生类中访问
公有字段
class C:
    
    def __init__(self):
        self.__foo = "私有字段"

    def func(self):
        print self.foo  # 类内部访问

class D(C):
    
    def show(self):
        print self.foo # 派生类中访问

obj = C()

obj.__foo     # 通过对象访问    ==> 错误
obj.func()  # 类内部访问        ==> 正确

obj_son = D();
obj_son.show()  # 派生类中访问  ==> 错误
私有字段

     方法 和 属性的访问和上述字段访问方式相同,都是 : 私有成员只能在类内部使用.

                           面向对象的嵌套                     

  面向对象的嵌套和函数的嵌套,列表的嵌套相似..

创建三个学校且三个学校的设施内容等都是一致.
"""

class School(object):
    def __init__(self, name, address):
        self.name = name
        self.address = address

    def speech(self):
        print('讲课')

obj1 = School('清华大学北京校区', '海淀校区')
obj2 = School('清华大学上海校区', '浦东校区')
obj3 = School('清华大学深圳校区', '南山校区')

class Teacher(object):
    def __init__(self, name, age, salary):
        self.name = name
        self.age = age
        self.__salary = salary     #工资应该是私有的
        self.school = None         #在老师没去学校的时候是没有教学的

t1 = Teacher('张三', 36, 35000)
t2 = Teacher('李四', 45, 55000)
t3 = Teacher('王五',28, 20000)
# ############## 老师分配校区
t1.school = obj1
t2.school = obj1
t3.school = obj2
# ####################################
# 查看t1老师,所在的校区名称/地址
print(t1.school.name)
print(t1.school.address)
print(t1.name)
print(t1.age)
t1.school.speech()
嵌套

猜你喜欢

转载自www.cnblogs.com/zmc940317/p/9549944.html