python-面向对象

什么是对象

万物皆对象
对象是具体的物体:有属性、行为,将很多零散的东西,封装为一个整体。
python是一门特别彻底的面向对象编程(OOP)的语言。所有都属于对象。

面向过程/面向对象

面向过程:在解决问题的时候,关注的是解决问题的每一个过程(步骤。
面向对象:在解决问题的时候,关注的是解决问题所需要的对象。
面向对象本身是对面向过程的封装
面向过程:重要的是按照步骤划分任务。
面向对象:按照步骤抽象成对象,确定属性和行为

某一个具体对象特征的抽象
作用:根据抽象的类,生成具体的对象

组成

名称、属性(静态的特征值)、方法(动态的操作):均是抽象的概念,在生产对象之后,才拥有具体的内容

定义类

大驼峰:英文首字母需要大写
class yawen:
    pass
ya = yawen()
print(type(ya))

实例化对象

Money也是变量名称

class Money:
    pass
one = Money()
print(one) #<__main__.Money object at 0x000001EEC60F2A90>
print(type(one)) #<class '__main__.Money'>
print(one.__class__) #<class '__main__.Money'>

属性

对象属性

增加:对象.属性
class Person:
    pass
p = Person()
p.age = 18
print(p.age) #18
#查看所有属性
print(p.__dict__) # {'age': 18}
查:访问对象没有的属性会报错
AttributeError: 'Person' object has no attribute 'sex'
修改:对象.属性 = 新的值
p.age = 20
print(p.age) #20
p.age = 20
print(p.age) #20
p.pets = ["小猫", "小狗", "小黑"]
print(p.pets, id(p.pets)) #['小猫', '小狗', '小黑'] 2368269277632
p.pets.append("小蔡")
print(p.pets, id(p.pets)) #['小猫', '小狗', '小黑', '小蔡'] 2368269217408
p.pets = [1]
print(p.pets, id(p.pets)) #[1] 2368269429120
删除:del p.属性
del p.age
print(p.age) #AttributeError: 'Person' object has no attribute 'age'
不同的对象之间不能互相访问属性。

类属性

类 其实也是一个对象,不过类是对象的模板。

增加

class Money:
    pass
Money.age = 18
print(Money, Money.age)#<class '__main__.Money'> 18
print(Money.__dict__)#{'__module__': '__main__', '__dict__': <attribute '__dict__' of 'Money' objects>, '__weakref__': <attribute '__weakref__' of 'Money' objects>, '__doc__': None, 'age': 18}
class Money:
    pass
Money.age = 18
print(Money, Money.age)#<class '__main__.Money'> 18
print(Money.__dict__)#{'__module__': '__main__', '__dict__': <attribute '__dict__' of 'Money' objects>, '__weakref__': <attribute '__weakref__' of 'Money' objects>, '__doc__': None, 'age': 18}

查询属性

class Money:
    age = 19
    count = 1
one = Money() 
print(one.__class__)#<class '__main__.Money'>

修改属性

class Money:
    age = 19
    count = 1
Money.age = 22
print(Money.age)#22

删除属性

del 类名.属性
del语句只删除直系属性
class Money:
    age = 19
    count = 1
one = Money()
del Money.age
#Money是type类型的对象
print(Money.age)#type object 'Money' has no attribute 'age'
print(one.age)#AttributeError: 'Money' object has no attribute 'age'
class Money:
    pass
one = Money()
one.__dict__ = {"name" : "niko", "age" : 18}
print(one.name)#niko
一般情况下,属性存储在__dict__的字典中,有些内置的对象没有__dict__这个属性
一般对象可以直接修改__dict__属性
但类的dict属性是只读,是不能写的。只可以通过setattr方式修改
类的属性由对象共享,如果类的属性修改,则对象属性应该做对应的修改。
class Money:
    age = 18
one = Money()
two = Money()
print(one.age, two.age)
Money.age = 20
print(one.age, two.age)

限制类可以添加的属性

__slots__ = [list]
class Person:
    __slots__ = ["age"]
p1 = Person()
p1.age = 9
p1.num = 10 #AttributeError: 'Person' object has no attribute 'num'

私有化属性

python没有私有化支持,但是可以用下划线完成伪私有的效果
类属性和实例属性遵从同样的规则
y:公有属性
_y:受保护的属性
__y:私有属性
#公有属性
#类内部访问 子类内部访问 模块内其他位置访问 跨模块访问(import 导入   from import 导入)
class Animal:
    x = 10
    def test(self):
        print(Animal.x)
    pass
class Dog(Animal):
    def test(self):
        print(Dog.x)
    pass
a = Animal()
a.test()#10 类的内部可以访问到x
dog = Dog()
dog.test()

print(Animal.x)#10
print(Dog.x)#10
#受保护的属性
#类内部访问 子类内部访问 模块内其他位置访问(会有警告 可以强行访问) 
#跨模块访问(import 导入也可以强行访问   from import 导入不能访问)
#可以在源文件加入__all__=[list],然后就可以使用from import *访问
class Animal:
    _x = 10
    def test(self):
        print(Animal._x)
    pass
class Dog(Animal):
    def test(self):
        print(Dog._x)
    pass
a = Animal()
a.test()#10 类的内部可以访问到x
dog = Dog()
dog.test()

print(Animal._x)#10
print(Dog._x)#10
#私有属性
#类内部访问 
#不可子类内部访问 
#不可模块内其他位置访问  
#跨模块访问(import 导入可以访问   from import 导入不能访问,__all__的技巧也可用)
class Animal:
    __x = 10
    def test(self):
        print(Animal.__x)
    pass
class Dog(Animal):
    def test(self):
        print(Dog.__x)
    pass
a = Animal()
a.test()#10 类的内部可以访问到x
dog = Dog()
dog.test()#type object 'Animal' has no attribute '__x'

print(Animal.__x)#type object 'Animal' has no attribute '__x'
print(Dog.__x)#type object 'Animal' has no attribute '__x'
私有属性的实现机制:名字重整:重改__x为另外一个名称,如_类名__x
目的:
1、防止外界直接访问
2、防止被子类同名称属性覆盖
#私有属性
#类内部访问 
#不可子类内部访问 
#不可模块内其他位置访问  
#跨模块访问(import 导入可以访问   from import 导入不能访问,__all__的技巧也可用)
class Animal:
    __x = 10
    def test(self):
        print(Animal.__x)
    pass
class Dog(Animal):
    def test(self):
        print(Dog.__x)
    pass
print(Animal.__dict__)#_Animal__x': 10
print(Animal._Animal__x)#10
用于:数据保护、数据过滤
class Person:
    def __init__(self, age):
        self.__age = age
p1 = Person(19)
p1.__age = -10
print(p1.__dict__) #{'_Person__age': 19, '__age': -10}
class Person:
    def __init__(self, age):
        self.__age = age
    def setAge(self, age):
        if isinstance(age, int) & (100 > age > 0):
            self.__age = age
        else:
            print("input error!")
    def getAge(self):
        return self.__age
p = Person(10)
p.setAge(20)
p.getAge()#20

xx_: 用于和系统的关键字作以区分,例如class_
__xx__:系统内置写法 如__dict__ __all__

只读属性

概念:一个属性,只能读取,不能写入。
应用场景:有些属性,只限在内部根据不同场景进行修改,对外界来说,只能读取不能修改
比如:电脑类的网速属性,网络状态属性。
class Person:
    def __init__(self):#全部隐藏 私有化
        self.__age = 18
    def getAge(self):
        return self.__age#允许只读
#装饰器改进
class Person(object):
    def __init__(self):
        self.__age = 18
    @property #以使用属性的方式来使用这个方法
    def age(self):
        return self.__age
p = Person()
p.age #18
p.age = 10#AttributeError: can't set attribute

property

作用:将一些属性的操作方法关联到某一个属性之中去。
经典类:没有继承object
新式类:继承了object
python3 默认是新式类
#方式1 
class Person(object):
    def __init__(self):
        self.__age = 18
        
    def get_age(self):
        return self.__age
        
    def set_age(self, value):
        self.__age = value
    
    age = property(get_age, set_age)
p = Person()
print(p.age)#18
p.age = 20
print(p.age, p.__dict__) #20 {'_Person__age': 20}

#方式2
class Person(object):
    def __init__(self):
        self.__age = 18
        
    @property
    def age(self):
        return self.__age
    @age.setter
    def age(self, value):
        self.__age = value
p = Person()
print(p.age)#18
p.age = 100
print(p.age)#100
class Person:
    #当我们通过实例,属性= 值来给一个实例添加一个属性,或者修改一个属性值的时候,都会调用
    #在方法的内部才会真正的把这个属性和对应的数据存储在__dict__中
    def __setattr__(self, key, value):
        print(key, value)
        if key == "age" and key in self.__dict__.keys():
            print("illega")
        else:
            self.__dict__[key] = value
p = Person()
print(p.__dict__) #{}
p.age = 18
print(p.age, p.__dict__)#18 {'age': 18}
p.age = 999
print(p.age, p.__dict__)#18 {'age': 18}

系统内置属性

类属性

类属性
__dict__:类的属性
__bases__:类的所有父类构成的元组(python支持多继承
__doc__:类的文档字符串
__name__:类名
__module__:类定义所在的模块

实例属性

__dict__:实例的属性
__class__:实例对应的类
class Person:
    """
    This is the class person
    """
    age = 19
    pass
print(Person.__dict__)#{'__module__': '__main__', '__doc__': '\n    This is the class person\n    ', 'age': 19, '__dict__': <attribute '__dict__' of 'Person' objects>, '__weakref__': <attribute '__weakref__' of 'Person' objects>}
print(Person.__bases__)#(<class 'object'>,)
print(Person.__doc__)#This is the class person
print(Person.__name__)#Person
print(Person.__module__)#__main__

方法

描述一个目标的行为动作
class Person:
    def eat(self):
        print(1)
p = Person()
p.eat()

方法的划分

划分依据:方法的第一个参数必须要接收的划分类型
实例方法:第一个参数必须是一个实例
类方法:第一个参数需要接受到一个类
静态方法:第一个参数并不默认接受任何值
三种方法均是存储在类之中的,没有存储在实例之中的。
class Person:
    def eat(self):
        print("这是实例方法", self)

    @classmethod
    def classmethod(cls):
        print("这是一个类方法", cls)

    @staticmethod
    def staticmethod():
        print("这是一个静态方法")

p = Person() 
p.eat()#这是实例方法 <__main__.Person object at 0x000002889F932F10>
Person.classmethod() #这是一个类方法 <class '__main__.Person'>
Person.staticmethod()#这是一个静态方法
p.staticmethod()#这是一个静态方法
Person.eat()#TypeError: eat() missing 1 required positional argument: 'self'
p.classmethod() #这是一个类方法 <class '__main__.Person'>
Person.staticmethod()#这是一个静态方法
p.staticmethod()#这是一个静态方法
调用类中的方法时,要保证不同类型的方法第一个参数接受到的数据,是他们想要的类型。

实例方法

标准调用:不用手动传参数,解释器会自动把调用对象本身传递过来的对象作为参数
其他调用:
类调用
间接调用
本质就是直接找到函数本身来调用
class Person:
    def eat(self, food):
        print("在吃饭", food, id(self)) #在吃饭 meat 1900029436832
p = Person()
p.eat("meat")
print(id(p))#1900029436832
#类调用
print(Person.eat)
Person.eat(123, "meat")#在吃饭 meat 2310333356208
#间接调用
func = Person.eat
func("123", 999)#在吃饭 999 2310337932464
#一般会将self直接传给方法,即使删除self参数也遵循这样的默认标准
class Person:
    def eat(self, food):
        print("在吃饭", food, id(self)) #在吃饭 meat 1900029436832
    def eat2(xxx):
        print(xxx)
p = Person()
p.eat2() #<__main__.Person object at 0x0000022F7F1CD040>

类方法

class Person:
    def eat(self, food):
        print("在吃饭", food, id(self)) #在吃饭 meat 1900029436832

    @classmethod
    def leimethod(cls):
        print(cls)
Person.leimethod()#<class '__main__.Person'>
p = Person()
#实例会被忽略
p.leimethod()#<class '__main__.Person'>

#子类调用父类的静态方法
#会将子类直接传递给cls
class A(Person):
    pass
A.leimethod()#<class '__main__.A'>

静态方法

class Person:
    def eat(self, food):
        print("在吃饭", food, id(self)) #在吃饭 meat 1900029436832

    @classmethod
    def leimethod(cls):
        print(cls)

    @staticmethod
    def jinmethod():
        print("Hello world")
p = Person()
p.jinmethod()#Hello world
Person.jinmethod()#Hello world

方法对属性的访问权限

class Person:
    age = 18
    def eat(self):#可以访问对象的属性
        print("实例方法")
        print(self.age)
        print(self.num)

    @classmethod#只能访问类属性
    def leimethod(cls):
        print(cls.age)

    @staticmethod #类和实例都无法访问
    def jinmethod():
        print(Person.age)#18
p = Person()
p.num = 100
#类属性
print(p.age)#18
print(Person.age)#18
#实例属性
print(p.num)#100

p.eat()#实例方法 18 100
Person.leimethod()#18

私有化方法

class Person:
    __age = 18
    def __run(self):#只能在类定义的内部
        print(self.__age)
p = Person()
print(Person.__dict__)#名字重整机制
p.__run()

内置方法

信息格式化操作

__str__
class Person:
    def __init__(self):
        self.name = "niko"
        self.age = 18
    def __str__(self):
        return "name:%s, age:%d" % (self.name, self.age)
p = Person()
print(p.name)
print(p.age)
print(p)#name:niko, age:18
__repr__
class Person:
    def __init__(self):
        self.name = "niko"
        self.age = 18
    def __str__(self):
        return "name:%s, age:%d" % (self.name, self.age)
    
    def __repr__(self):
        return "hello world"
p = Person()
print(p.name)
print(p.age)
print(repr(p))#hello worlda

元类

概念:创建类对象的类(type类)
num = 10
print(num.__class__)#<class 'int'>
s = "abc"
print(s.__class__)#<class 'str'>
class Person:
    pass
print(Person.__class__)#<class 'type'>
print(int.__class__)#<class 'type'>
print(set.__class__)#<class 'type'>()
print(type.__class__)#<class 'type'> 再往上就没了!!!元类是最初的类

补充

类的创建方式

#方式1
class Person:
    count = 0
    def run(self):
        pass
#方式2 使用元类 
#第一个参数是类的name 第二个参数是元组,也就是该类的父类 第三个参数是dict
def run(self):
    pass
Dog = type("Dog", (), {"name" : "niko", "run" : run})
dog = Dog()
print(dog.name)#niko
dog.run()
类对象先通过自己的属性__metaclass__来指明自己从哪个类对象创建而来
找不到该属性则去找自己的父类的__metaclass__来找自己的 元类
如果还没找到就在模块里面去找,也就是文件中的全局变量区域找有无__metaclass__
如果还没有就会找到type,根据type创建类对象。
__metaclass__ = type
class Person:
    __metaclass__ = type#可以是自己定义的类
    pass

class Person(metaclass = type):
    pass

class Animal:
    pass
class Person(Animal):
    pass
元类应用场景:
1、拦截类的创建
2、修改类
3、返回修改之后的类

类的描述

方便理清逻辑思路
方便多人合作时候开发时候沟通
方便生成项目文档
class Person:
    """
    类的作用、构造函数、类属性的描述
    Attributes:
        count : int 代表人的数目
    """
    count = 1
    def run(self, step):
        """
        :param step : 参数的含义,类型,是否有默认值
        :return : 返回的结果的含义,返回数据的类型
        """
        print("hello world")
help(Person)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值