面向对象

一.面向对象三大特性
封装   (把多个方法都需要的参数放在init方法中)
class f1(object):
    def __init__(self,name,age,adress,country):
        self.name=name
        self.age=age
        self.adress=adress
        self.country=country

obj=f1('haha',18,'beijing','china')

继承 (多个方法用到共同一个方法就可用继承的模式写,提高代码复用率,简化代码)

class f1():
    def func(self):
        pass
class f2(f1):
    def func1(self):
        pass
class f3(f1):
    def func2(self):
        pass
obj2=f2()
obj3=f3()
obj2.func()
obj3.func()

多态  (鸭子模型)

class f1():
    def __init__(self,m):
        print(m)
obj=f1(1)
obj1=f1('haha')
obj2=f1([12,123])
obj3=f1({'hah':'123','lala':'321'})
obj4=f1(True)
obj5=f1((1,2,3))

二. 类的成员

      1. 变量:
                - 实例变量(字段)
                    - 公有实例变量(字段)
                    - 私有实例变量(字段)
                - 类变量(静态字段)
                    - 公有类变量(静态字段)
                    - 私有类变量(静态字段)
                
  实例一:
                        class Foo:
                            # 类变量(静态字段)
                            country = "中国"
                            
                            def __init__(self,name):
                                # 实例变量(字段)
                                self.name = name  
    
                            def func(self):
                                pass
             
                        obj1 = Foo('季红')
                        obj2 = Foo('王晓东')
                        
                        Foo.country

 派生类无法调用私有字段.

无法访问:
                        class Base(object):
                            __secret = "受贿"
                        class Foo(Base):
                            def func(self):
                                print(self.__secret)
                                print(Foo.__secret)

                        obj = Foo()
                        obj.func()

可以访问:

                        class Base(object):
                            __secret = "受贿"
                            def zt(self):
                                print(Base.__secret)

                        class Foo(Base):
                            def func(self):
                                print(self.__secret)
                                print(Foo.__secret)

                        obj = Foo()
                        obj.zt()

2.方法:

  - 实例方法
                        class Foo(object):
                            def __init__(self, name):
                                self.name = name
                            # 实例方法
                            def func(self):
                                print(self.name)
                                
                        obj = Foo('..')
                        obj.func()

  - 静态方法

                        class Foo(object):
                            def __init__(self, name):
                                self.name = name
                            # 静态方法,如果方法无需使用对象中封装的值,那么就可以使用静态方法
                            @staticmethod
                            def display(a1,a2):
                                return a1 + a2
                        Foo.display(1,3)

 - 类方法      

                         class Foo(object)
                          # 类方法,cls是类
                            @classmethod
                            def show(cls,x1,x2):
                                print(cls,x1,x2)
                        # 执行类方法
                        Foo.show(1,8)

面试题: 静态方法/类方法和实例方法的区别?  

(1)定义(参数)            
静态方法可以不传参数            前面加@staticmethod          
类方法必须至少有1个参数cls      前面加@classmethod
实例方法必须有1个参数self          
(2)调用
静态方法首选类名调用                  类名.类方法(首选)       对象.类方法
类方法首选类名调用                    类名.类方法(首选)       对象.类方法                                                            
实例方法必须用实例化对象去调用                               对象.实例方法(唯一调用方法)

3. 属性(通过方法改造出来):

  示例:
               
                      class Foo(object):
                        def __init__(self):
                            pass
                        @property
                        def start(self):
                            return 1
                        @property
                        def end(self):
                            return 10
                    obj = Foo()
                    print(obj.start)
                    print(obj.end)

 

                        # 总结:
                        #     1. 编写时
                        #            - 方法上方写 @property
                        #            - 方法参数:只有一个self
                        #     2. 调用时:无需加括号  对象.方法
                        #     3. 应用场景: 对于简单的方法,当无需传参且有返回值时,可以使用 @property
 三.嵌套
#3 用面向对象的嵌套表示:学生、班级、老师的关系,并创建相关对象进行嵌套【根据自己的理解编写】;

class Teacher():
    def __init__(self, name, age, kecheng, xingbie):
        self.name = name
        self.age = age
        self.kecheng = kecheng
        self.xingbie = xingbie

class Banji():
    def __init__(self,nianji,num,teacher=None):
        self.nianji=nianji
        self.num=num
        self.teacher=teacher

class Student():
    def __init__(self,num,name,xingbie,age,banji=None):
        self.num=num
        self.name=name
        self.xingbie=xingbie
        self.age=age
        self.banji=banji

teacher=Teacher("老师",'30岁','python','男')
banji=Banji('3年级','10班',teacher)
student=Student("学号12",'嘻嘻','男','18岁',banji)
print(student.num,student.name,student.xingbie,student.age,student.banji.num,student.banji.teacher.name)

四.主动调用其他类的成员

方式一: 

      class Base(object):

         def f1(self):
            print('5个功能')

      class Foo(object):

         def f1(self):
            print('3个功能')
            Base.f1(self)

      obj = Foo()
      obj.f1()
#总结:

#Base.实例方法(自己传self)与继承无关


方式二:         按照类的继承顺序,找下一个.

class Foo(object):
         def f1(self):
            super().f1()
            print('3个功能')

      class Bar(object):
         def f1(self):
            print('6个功能')

      class Info(Foo,Bar):
         pass

      # obj = Foo()
      # obj.f1()

      obj = Info()
      obj.f1()

五.特殊成员

class Foo(object):

    def __init__(self,a1,a2):
        self.a1 = a1
        self.a2 = a2
    
    def __call__(self, *args, **kwargs):
        print(11111,args,kwargs)
        return 123

    def __getitem__(self, item):
        print(item)
        return 8

    def __setitem__(self, key, value):
        print(key,value,111111111)

    def __delitem__(self, key):
        print(key)

    def __add__(self, other):
        return self.a1 + other.a2

    def __enter__(self):
        print('1111')
        return 999

    def __exit__(self, exc_type, exc_val, exc_tb):
        print('22222')

# 1. 类名() 自动执行 __init__
 obj = Foo(1,2)

# 2. 对象() 自动执行 __call__
ret = obj(6,4,2,k1=456)

# 3. 对象['xx']  自动执行 __getitem__
 ret = obj['yu']
print(ret)

# 4. 对象['xx'] = 11  自动执行 __setitem__
 obj['k1'] = 123

# 5. del 对象[xx]     自动执行 __delitem__
del obj['uuu']

# 6. 对象+对象         自动执行 __add__
obj1 = Foo(1,2)
obj2 = Foo(88,99)
ret = obj2 + obj1
print(ret)

# 7. with 对象        自动执行 __enter__ / __exit__
obj = Foo(1,2)
with obj as f:
print(f)
print('内部代码')

# 8. 真正的构造方法
 class Foo(object):
     def __init__(self, a1, a2):     # 初始化方法
         """
         为空对象进行数据初始化
         :param a1:
         :param a2:
         """
         self.a1 = a1
         self.a2 = a2

     def __new__(cls, *args, **kwargs): # 构造方法
         """
         创建一个空对象
         :param args:
         :param kwargs:
         :return:
       
         return object.__new__(cls) # Python内部创建一个当前类的对象(初创时内部是空的.).

 obj1 = Foo(1,2)
 print(obj1)

 obj2 = Foo(11,12)
 print(obj2)
9.__str__
            class Foo(object):
                def __init__(self):
                    pass

                def func(self):
                    pass

                def __str__(self):
                    return "F1"

            obj = Foo()
            print(obj,type(obj))
10.__doc__
            
            class Foo(object):
                """
                asdfasdfasdfasdf
                """
                def __init__(self):
                    pass

                def func(self):
                    pass

                def __str__(self):
                    return "F1"

            obj = Foo()
            print(obj.__doc__)
11.__dict__
            
            class Foo(object):
                def __init__(self,name,age):
                    self.name = name
                    self.age = age

                def func(self):
                    pass

            obj1 = Foo('刘博文',99)
            obj2 = Foo('史雷',89)


            print(obj1.__dict__) # {'name': '刘博文', 'age': 99}
            print(obj2.__dict__) # {'name': '史雷', 'age': 89}
        __iter__
            # l1是list类的一个对象,可迭代对象
            l1 = [11,22,33,44]

            # l2是list类的一个对象,可迭代对象
            l2 = [1,22,3,44]


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

                def func(self):
                    pass

                def __iter__(self):
                    # return iter([11,22,33,44,55,66])

                    yield 11
                    yield 22
                    yield 33

            # obj1是Foo类的一个对象,可迭代对象
            """
            如果想要把不可迭代对象 -> 可迭代对象
            1. 在类中定义__iter__方法
            2. iter内部返回一个迭代器(生成器也是一种特殊迭代器)
            """
            obj1 = Foo('刘博文',99)

            for item in obj1:
                print(item)

六.isinstance/issubclass/type

(1)isinstance(对象,类),检查第一个参数(对象)是否是第二个参数(类及父类)的实例。
           
   class Base(object):
      pass

   class Foo(Base):
      pass

   obj1 = Foo()
   print(isinstance(obj1,Foo))  # 检查第一个参数(对象)是否是第二个参数(类及父类)的实例。
   print(isinstance(obj1,Base)) # 检查第一个参数(对象)是否是第二个参数(类及父类)的实例。


   obj2 = Base()
   print(isinstance(obj2,Foo))  # 检查第一个参数(对象)是否是第二个参数(类及父类)的实例。
   print(isinstance(obj2,Base)) # 检查第一个参数(对象)是否是第二个参数(类及父类)的实例。

(2)issubclass(类,类):              #检查第一个参数是否是第二个参数的 子子孙孙类
class Base(object):
pass

class Foo(Base):
pass

class Bar(Foo):
pass

print(issubclass(Bar,Base)) # 检查第一个参数是否是第二个参数的 子子孙孙类

(3)type(对象):获取当前对象是由那个类创建。
"""
class Foo(object):
pass

obj = Foo()

print(obj,type(obj)) # 获取当前对象是由那个类创建。
if type(obj) == Foo:
print('obj是Foo类型')
"""

# #### 练习题
"""
class Foo(object):
pass

class Bar(object):
pass

def func(*args):
foo_counter =0
bar_counter =0
for item in args:
if type(item) == Foo:
foo_counter += 1
elif type(item) == Bar:
bar_counter += 1
return foo_counter,bar_counter

# result = func(Foo(),Bar(),Foo())
# print(result)

v1,v2 = func(Foo(),Bar(),Foo())
print(v1,v2)
"""
"""
给你一个参数,判断对象是不是由某一个指定类? type --> type(obj) == Foo
给你一个参数,判断对象是不是由某一个指定类或其父类? isinstance --> instance(obj,Foo)
"""

七.方法和函数

称谓:
            类,方法
            外,函数
        到底方法函数?
            对象.xxx  --> xxx就是方法
            类.xxx    --> xxx就是函数
            xxx       --> xxx就是函数
        打印查看:
            function 
            method 
            
        代码检查:
            from types import MethodType,FunctionType
            def check(arg):
                """
                检查arg是方法还是函数?
                :param arg:
                :return:
                """
                if isinstance(arg,MethodType):
                    print('arg是一个方法')
                elif isinstance(arg,FunctionType):
                    print('arg是一个函数')
                else:
                    print('不知道是什么')

八.反射

getattr(obj,"func")  # 根据字符串为参数(第二个参数),去对象(第一个参数)中寻找与之同名的成员。
            getattr # 根据字符串的形式,去对象中找成员。
            hasattr # 根据字符串的形式,去判断对象中是否有成员。
            setattr # 根据字符串的形式,动态的设置一个成员(内存)
            delattr # 根据字符串的形式,动态的删除一个成员(内存)
        应用一:
            # by luffycity.com
            from types import FunctionType
            import handler

            while True:
                print("""
                系统支持的函数有:
                    1. f1
                    2. f2
                    3. f3
                    4. f4
                    5. f5
                """)
                val = input("请输入要执行的函数:") # val = "f1"

                # 错误
                # handler.val()
                if hasattr(handler,val):
                    func_or_val = getattr(handler,val)     # 根据字符串为参数,去模块中寻找与之同名的成员。
                    if isinstance(func_or_val,FunctionType):
                        func_or_val()
                    else:
                        print(func_or_val)
                else:
                    print('handler中不存在输入的属性名')

                # 正确方式
                """
                if val == 'f1':
                    handler.f1()
                elif val == 'f2':
                    handler.f2()
                elif val == 'f3':
                    handler.f3()
                elif val == 'f4':
                    handler.f4()
                elif val == 'f5':
                    handler.f5()
                """
        
        应用二:
            
            class Account(object):
                func_list = ['login', 'logout', 'register']

                def login(self):
                    """
                    登录
                    :return:
                    """
                    print('登录111')

                def logout(self):
                    """
                    注销
                    :return:
                    """
                    print('注销111')

                def register(self):
                    """
                    注册
                    :return:
                    """
                    print('注册111')

                def run(self):
                    """
                    主代码
                    :return:
                    """
                    print("""
                        请输入要执行的功能:
                            1. 登录
                            2. 注销
                            3. 注册
                    """)

                    choice = int(input('请输入要执行的序号:'))
                    func_name = Account.func_list[choice-1]

                    # func = getattr(Account,func_name) # Account.login
                    # func(self)

                    func = getattr(self, func_name)  # self.login
                    func()

            obj1 = Account()
            obj1.run()

            obj2 = Account()
            obj2.run()

 


            
posted @ 2018-08-30 17:37  冒蓝火的加特林哒哒哒  阅读(80)  评论(0编辑  收藏  举报