Принятый ответ работает, но немного больше объяснений не повредит.
Атрибуты класса не становятся атрибутами экземпляра при создании экземпляра. Они становятся атрибутами экземпляра, когда им присваивается значение.
В исходном коде значение no присваивается атрибуту list
после создания экземпляра; поэтому он остается атрибутом класса. Определение списка внутри __init__
работает, потому что __init__
вызывается после создания экземпляра. В качестве альтернативы, этот код также выдаст желаемый результат:
>>> class a:
list = []
>>> y = a()
>>> x = a()
>>> x.list = []
>>> y.list = []
>>> x.list.append(1)
>>> y.list.append(2)
>>> x.list.append(3)
>>> y.list.append(4)
>>> print(x.list)
[1, 3]
>>> print(y.list)
[2, 4]
Однако запутанный сценарий в вопросе никогда не случится с неизменяемыми объектами, такими как числа и строки, поскольку их значение не может быть изменено без назначения. Например, код, аналогичный оригиналу со строковым атрибутом, работает без каких-либо проблем:
>>> class a:
string = ''
>>> x = a()
>>> y = a()
>>> x.string += 'x'
>>> y.string += 'y'
>>> x.string
'x'
>>> y.string
'y'
Итак, чтобы суммировать: атрибуты класса становятся атрибутами экземпляра тогда и только тогда, когда им присваивается значение после создания, в методе __init__
или нет. Это хорошо, потому что таким образом вы можете иметь статические атрибуты, если никогда не присваиваете значение атрибуту после создания экземпляра.
Это пример, показывающий, как я это сделал, разместив три оси вручную на фигуре.
from __future__ import division, unicode_literals
import matplotlib.pyplot as plt
import numpy as np
plt.close('all')
# ----- PREPARE DATA ----
t = np.arange(0, 7 * 10**5, 10)
x = np.abs(np.sin(t/10.**2)) * 300
# ----- FIG CREATION ----
fig = plt.figure(figsize=(8, 5), facecolor='white')
# Margins (dimensions are in inches):
left_margin = 0.6 / fig.get_figwidth()
right_margin = 0.25 / fig.get_figwidth()
bottom_margin = 0.75 / fig.get_figheight()
top_margin = 0.25 / fig.get_figwidth()
mid_margin = 0.1 / fig.get_figwidth() # horizontal space between subplots
# ----- DEFINE PARAMETERS FOR EACH AXE ----
# Proportion of the figure's width taken by each axe (the sum must == 1):
f = [0.5, 0.3, 0.2]
xmin = [200, 50, 0] # xaxis minimum values for each axe
xmax = [8200, 200, 50] # xaxis maximum values for each axe
xscl = [2000, 50, 10] # xaxis scale for each axe
ymin, ymax = 0, 320 # yaxis minimum and maximum values
colors = ['green', 'blue', 'red'] # colors of each plot
labels = ['label1', 'label2', 'label3'] # labels of each plot for the legend
Naxes = len(f) # Total number of axes to add to the figure.
x0, y0 = left_margin, bottom_margin # origin point of the axe
h = 1 - (bottom_margin + top_margin) # height of the axe
# total width of the axes:
wtot = 1 - (left_margin + right_margin + (Naxes-1)*mid_margin)
lines = [] # to store handles for generating the legend later on
for i in range(Naxes):
# ----- AXES CREATION ----
w = wtot*f[i] # width of the current axe
ax = fig.add_axes([x0, y0, w, h], frameon=True, axisbg='none')
if i == 0: # First axe to the left
ax.spines['right'].set_visible(False)
ax.tick_params(right='off', labelright='off')
elif i == Naxes-1: # Last axe to the right
ax.spines['left'].set_visible(False)
ax.tick_params(left='off', labelleft='off',
right='off', labelright='off')
else:
ax.spines['left'].set_visible(False)
ax.spines['right'].set_visible(False)
ax.tick_params(left='off', labelleft='off',
right='off', labelright='off')
# origin point of the next axe to be added to the figure:
x0 += w + mid_margin
# ----- SETUP XTICKS ----
if i == Naxes-1:
xticks = np.arange(xmin[i], xmax[i] + xscl[i]/2, xscl[i])
else:
xticks = np.arange(xmin[i]+xscl[i], xmax[i] + xscl[i]/2, xscl[i])
ax.set_xticks(xticks)
ax.xaxis.set_ticks_position('bottom')
ax.tick_params(axis='x', direction='out', labelsize=8)
xticks_minor = np.arange(xmin[i], xmax[i] + xscl[i]/5., xscl[i] / 5.)
ax.set_xticks(xticks_minor, minor=True)
ax.tick_params(axis='x', which='minor', direction='out')
# ----- PLOT DATA ----
line, = ax.plot(t, x, color=colors[i])
lines.append(line) # for plotting the legend
ax.axis([xmin[i], xmax[i], ymin, ymax])
ax.invert_xaxis()
# ---- SET XAXIS LABEL ----
fig.axes[0].set_xlabel('Time (years)', fontsize=12, va='bottom', ha='center')
fig.axes[0].xaxis.set_label_coords(0.5, 0.05, transform=fig.transFigure)
# ----- LEGEND ----
fig.axes[0].legend(lines, labels, loc=(0.1, 0.1), ncol=1, fancybox=True,
fontsize=12)
# ----- SHOW FIG ----
fig.savefig('SingleAxeThreeScale.png')
plt.show()
В результате:
Вы неправильно вызываете plt.subplots
. Вот пример использования по умолчанию
(nrows = 1, ncols = 1, sharex = False, sharey = False, squeeze = True, subplot_kw = None, gridspec_kw = None, ** fig_kw)
blockquote>Кажется, что вы хотите 5 подзаговоров в строке, поэтому установите
nrows=1
иncols=5
fig,axs = plt.subplots(nrows=1,ncols=5,sharey=True) ax, ax2, ax3, ax4, ax5 = axs
Проблема 2
Вы необходимо правильно установить шипы - вы хотите, чтобы слева и справа были видны. Это легко сделать с помощью функции:
def multi_spine_adj( axs): axs[0].spines['right'].set_visible(False) axs[0].yaxis.tick_left() for ax in axs[1:-1]: ax.spines['right'].set_visible(False) ax.spines['left'].set_visible(False) axs[-1].spines['left'].set_visible(False) axs[-1].yaxis.tick_right() #wvln0 = np.linspace( 0,5,50) # make some fake data #alb0 = np.random.random(50) #make some fake data opts = {'linestyle':'-', 'marker':'o', 'color':'r','linewidth':1,'label':'Haze = 0T'} fig,axs = plt.subplots(1,5,sharey=True) xlims = [(0.15,1.10), (1.15,2.25), (1.20,1.30), (1.55,1.65), (1.95,2.15)] for i,ax in enumerate(axs): x1,x2 = xlims[i] ax.plot(wvln0,alb0,**opts) ax.set_xlim(x1,x2) multi_spine_adj(axs) plt.show()
Совет
Обратите внимание, как вы можете легко перебирать
axs
, это делает ваш код более чистым и простым в изменении ( если вы хотите добавить больше перерывов, например)