魔法方法 (Magic Methods) 是Python中的内置函数,一般以双下划线开头和结尾,例如__ init__ 、 __del__ 等.之所以称之为魔法方法,是因为这些方法会在进行特定的操作时会自动被调用.
在Python中,可以通过dir()方法来查看某个对象的所有方法和属性,其中双下划线开头和结尾的就是该对象的魔法方法.以字符串对象为例:
可以看到字符串对象有 __add__ 方法,所以在Python中可以直接对字符串对象使用"+"操作,当Python识别到"+"操作时,就会调用该对象的 __add__ 方法.有需要时我们可以在自己的类中重写 __add__ 方法来完成自己想要的效果.
我们重写了 __add__ 方法,当Python识别"+"操作时,会自动调用重写后的 __add__ 方法.可以看到,魔法方法在类或对象的某些事件出发后会自动执行,如果希望根据自己的程序定制特殊功能的类,那么就需要对这些方法进行重写.使用魔法方法,我们可以非常方便地给类添加特殊的功能.
①.、构造与初始化
__ new __ 、 __ init __ 这两个魔法方法常用于对类的初始化操作.上面我们创建a1 = A("hello")时,但首先调用的是 __ new __ ;初始化一个类分为两步:
a.调用该类的new方法,返回该类的实例对象
b.调用该类的init方法,对实例对象进行初始化.
__new__ (cls, *args, **kwargs)至少需要一个cls参数,代表传入的类.后面两个参数传递给 __ init __ .在 __ new __ 可以决定是否继续调用 __ init __ 方法,只有当 __ new __ 返回了当前类cls的实例,才会接着调用 __ init __ .结合 __ new __ 方法的特性,我们可以通过重写 __ new __ 方法实现Python的单例模式:
可以看到虽然创建了两个对象,但两个对象的地址相同.
方法主要对对象的属性进行访问、定义、修改时起作用.主要有:
__getattr__(self, name): 定义当用户试图获取一个属性时的行为.
__getattribute__(self, name):定义当该类的属性被访问时的行为(先调用该方法,查看是否存在该属性,若不存在,接着去调用getattr).
__setattr__(self, name, value):定义当一个属性被设置时的行为.
当初始化属性时如self.a=a时或修改实例属性如ins.a=1时本质时调用魔法方法self. __ setattr __ (name,values);当实例访问某个属性如ins.a本质是调用魔法方法a. __ getattr __ (name)
有一些方法可以让我们自己定义自己的容器,就像Python内置的List,Tuple,Dict等等;容器分为可变容器和不可变容器.
如果自定义一个不可变容器的话,只能定义__ len__ 和__ getitem__ ;定义一个可变容器除了不可变容器的所有魔法方法,还需要定义__ setitem__ 和__ delitem__ ;如果容器可迭代.还需要定义__ iter __.
__len__(self):返回容器的长度
__getitem__(self,key):当需要执行self[key]的方式去调用容器中的对象,调用的是该方法
__setitem__(self,key,value):当需要执行self[key] = value时,调用的是该方法
__iter__(self):当容器可以执行 for x in container:,或者使用iter(container)时,需要定义该方法
下面举一个例子,实现一个容器,该容器有List的一般功能,同时增加一些其它功能如访问第一个元素,最后一个元素,记录每个元素被访问的次数等.
这类方法的使用场景主要在你需要定义一个满足需求的容器类数据结构时会用到,比如可以尝试自定义实现树结构、链表等数据结构(在collections中均已有),或者项目中需要定制的一些容器类型.
魔法方法在Python代码中能够简化代码,提高代码可读性,在常见的Python第三方库中可以看到很多对于魔法方法的运用.
所以呢当前这篇文章仅是抛砖引玉,真正的使用需要在开源的优秀源码中以及自身的工程实践中不断加深理解并合适应用.
类是对象的模板,是抽象的.
构造函数 init 是Python魔术方法之一,如图魔术方法
我们通过类模版去创建类的实例对象,然后再调用类定义的功能.
那实例对象的属性是通过什么来初始化的?
这时候Python引入来构造函数 init
构造函数,会在创建实例对象之后Python会自动执行此方法,把初始化的属性特点放到实例对象里.
通过前面的学习,我们知道一个python对象包含三个部分:id(识别码),type(对象类型),value(对象的值)
那么我们进一步深入对象包含的三部分:
我们通过类创建实例对象后,需要定义构造函数 init ()方法.
构造方法用于执行实例对象的初始化工作,即对象创建之后,初始化当前对象的相关的属性,无返回值
构造函数重点 :
我们通过栗子来学习构造函数的过程
构造函数初始化实例对象过程如下:
①Animal类会通过默认的 new ()方法为实例对象在堆内存中为开辟一个空间
敲黑板,重点来啦~
拓展:
我们今天学习了构造函数 init (),其在创建对象之后被Python自动调用初始化实例对象属性数据值,无返回值,并且构造函数不能被显示调用.
创建对象时,如果需要,构造函数可以接受参数.当创建没有构造函数的类时,Python会自动创建一个不执行任何操作的默认构造函数.
每个类必须有一个构造函数,即使它只依赖于默认构造函数
好啦,好了,全部的本期内容,欢迎大佬评论区指正~
python open函数的newline参数控制着如何转换和输出换行符,下面是官方解释:
对于读取:
当newline为 None 时,会启用通用换行模式,输入中的 '\n' (linux系统换行符), '\r' (mac换行符), '\r\n' (windows换行符)都会被转换成'\n'.
当newline为 '' 时,同样会启用通用换行模式,三种换行符都会被当作换行符且原模原样的返回给你,不会被转换.
对于输出:
当newline为 None 时,所有 '\n' 会被转换成系统默认的换行符.所以比如windows下写入一行末尾加上 '\r\n' ,实际上会变成 '\r\r\n' .
当newline为 '' 或 '\n' 时,不进行转换.
当newline为其他选项时, '\n' 会被转换成对应的换行符.
__new__: 对象的创建,是一个静态方法,第一个参数是cls.(想想也是,不可能是self,对象还没创建,哪来的self)
__init__ : 对象的初始化, 是一个实例方法,第一个参数是self.
__call__ : 对象可call,注意不是类,是对象.
先有创建,才有初始化.即先__new__,而后__init__.
上面说的不好理解,看例子.
①对于__new__
可以看到,输出来是一个Bar对象.
__new__方法在类定义中不是必须写的,如果没定义,默认会调用object.__new__去创建一个对象.如果定义了,就是override,可以custom创建对象的行为.
聪明的读者可能想到,既然__new__可以custom对象的创建,那我今天这一节做一下手脚,每次创建对象都返回同一个,那不就是单例模式了吗?没错,就是这样.可以观摩<<飘逸的python - 单例模式乱弹>>
定义单例模式时,因为自定义的__new__重载了父类的__new__,所以要自己显式调用父类的__new__,即object.__new__(cls, *args, **kwargs),或者用super().,不然就不是extend原来的实例了,而是替换原来的实例.
使用Python写过面向对象的代码的同学,可能对 __init__ 方法已经非常熟悉了,__init__ 方法通常用在初始化一个类实例的时候.例如:
这样便是__init__最普通的用法了.但__init__其实不是实例化一个类的时候第一个被调用 的方法.当使用 Persion(name, age) 这样的表达式来实例化一个类时,最先被调用的方法 其实是 __new__ 方法.
总结,在Python中,类的行为就是这样,__new__、__init__、__call__等方法不是必须写的,会默认调用,如果自己定义了,就是override,可以custom.既然override了,通常也会显式调用进行补偿以达到extend的目的.
这也是为什么会出现"明明定义def _init__(self, *args, **kwargs),对象怎么不进行初始化"这种看起来诡异的行为.(注,这里_init__少写了个下划线,因为__init__不是必须写的,所以这里不会报错,而是当做一个新的方法_init__)
报错意思是变量'new_fjcb'事先没有被定义.
因为你用input传入赋值给的yj变量,函数fjz需要传入一个值赋值给变量'new_fjcb',而你这里没有传入,直接就调用函数fjz,所以报错
补充一点:变量必须要先定义赋值再使用,不然就会报错NameError
python的常用内置函数
①abs() 函数返回数字的绝对值
dict()
{} ? ? ?#创建一个空字典类似于u={},字典的存取方式一般为key-value
help('math')查看math模块的用处
help(a)查看列表list帮助信息
dir(help)
['__call__', '__class__', '__delattr__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__gt__', '__hash__', '__init__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__']
a
①.0
next(it)
id(a)
a=["tom","marry","leblan"]
list(enumerate(a))
oct(10)
①.0. bin() 返回一个整数 int 或者长整数 long int 的二进制表示
bin(10)
'0b1010'
'0b1111'
①.1.eval() 函数用来执行一个字符串表达式,并返回表达式的值
f=open('test.txt')
bool()
False
bool(1)
True
bool(10)
bool(10.0)
isinstance(a,int)
isinstance(a,str)
class ? User(object):
? ? def__init__(self):
class Persons(User):
? ? ? ? ? super(Persons,self).__init__()
float(1)
①0
float(10)
①.0.0
iter(a)
for i in iter(a):
... ? ? ? ? print(i)
...
tuple(a)
s = "playbasketball"
len(s)
len(a)
class User(object):
? ?def __init__(self,name):
? ? ? ? ? ? self.name = name
? def get_name(self):
? ? ? ? ? ? return self.get_name
? @property
? ?def name(self):
? ? ? ? ? ?return self_name
list(b)
range(10)
range(0, 10)
class w(object):
a = w()
getattr(a,'s')
complex(1)
(1+0j)
complex("1")
max(b)
class Num(object):
...? ? a=1
.. print1 = Num()
print('a=',print1.a)
a= 1
print('b=',print1.b)
print('c=',print1.c)
delattr(Num,'b')
Traceback (most recent call last):? File "", line 1, inAttributeError: 'Num' object has no attribute 'b'
hash("tom")
a= set("tom")
b = set("marrt")
a,b
({'t', 'm', 'o'}, {'m', 't', 'a', 'r'})
ab#交集
{'t', 'm'}
a|b#并集
{'t', 'm', 'r', 'o', 'a'}
a-b#差集
{'o'}
以上就是土嘎嘎小编大虾米为大家整理的相关主题介绍,如果您觉得小编更新的文章只要能对粉丝们有用,就是我们最大的鼓励和动力,不要忘记讲本站分享给您身边的朋友哦!!