[英]Why is my Python mysql class __init__ function trying to overload the mysql package __init__ function?
[英]Python create if elif in __init__ for package and function
我将所有已定义的函数组合到一个class
并使用if
, elif
进行操作。
我将在下面解释。
首先,我有3种类型的plot, combo
, line
和bar
。
我知道如何为这三个图分别定义函数。
其次,我想使用if
将这3个图组合到一个包中。
我试过的代码是:
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
class AP(object):
def __init__(self, dt, date, group, value, value2, value3, value4, value5, value6, TYPE):
self.dt = dt
self.date = date
self.group= carrier
self.value = value
self.col1 = col1
self.col2 = col2
self.col3 = col3
self.col4 = col4
self.TYPE = TYPE
if self.TYPE == "combo":
def ComboChart(self, dt, date, group, value, TYPE):
dataset = pd.read_csv(dt)
dataset['date'] = pd.to_datetime(dataset[date])
dataset['yq'] = pd.PeriodIndex(dataset['date'], freq='Q')
dataset['qtr'] = dataset['date'].dt.quarter
dataset = dataset.groupby([carrier, 'yq', 'qtr'])[value].sum().reset_index()
dataset['total.YQGR'] = dataset[value] / dataset.groupby(['qtr', carrier])[value].transform('shift') - 1
dataset = dataset[np.isfinite(dataset['total.YQGR'])]
dataset['total.R'] = dataset[value] / dataset.groupby(group)[value].transform('first')
dataset.yq = dataset.yq.astype(str)
fig, ax1 = plt.subplots(figsize=(12,7))
ax2=ax1.twinx()
sns.lineplot(x='yq',y='total.R', data=dataset, hue=group, ax=ax1, legend = None, palette = ('navy', 'r'), linewidth=5)
ax1.set_xticklabels(ax1.get_xticks(), rotation=45, fontsize=15, weight = 'heavy')
ax1.set_xlabel("", fontsize=15)
ax1.set_ylabel("")
ax1.set_ylim((0, max(dataset['total.R']) + 0.05))
sns.barplot(x='yq', y='total.YQGR', data=dataset, hue=group, ax=ax2, palette = ('navy', 'r'))
ax2.set_yticklabels(['{:.1f}%'.format(a*100) for a in ax2.get_yticks()])
ax2.set_ylabel("")
ax2.set_ylim((min(dataset['total.YQGR']) - 0.01, max(dataset['total.YQGR']) + 0.2))
ax2.get_legend().remove()
ax2.legend(bbox_to_anchor=(-0.35, 0.5), loc=2, borderaxespad=0., fontsize = 'xx-large')
for groups in ax2.containers:
for bar in groups:
if bar.get_height() >= 0:
ax2.text(
bar.get_xy()[0] + bar.get_width()/1.5,
bar.get_height() + 0.003,
'{:.1f}%'.format(round(100*bar.get_height(),2)),
color='black',
horizontalalignment='center',
fontsize = 12, weight = 'heavy'
)
else:
ax2.text(
bar.get_xy()[0] + bar.get_width()/1.5,
bar.get_height() - 0.008,
'{:.1f}%'.format(round(100*bar.get_height(),2)),
color='black',
horizontalalignment='center',
fontsize = 12, weight = 'heavy'
)
ax1.yaxis.set_visible(False)
ax2.yaxis.set_visible(False)
ax2.xaxis.set_visible(False)
ax1.spines["right"].set_visible(False)
ax1.spines["left"].set_visible(False)
ax1.spines["top"].set_visible(False)
ax1.spines["bottom"].set_visible(False)
ax2.spines["right"].set_visible(False)
ax2.spines["left"].set_visible(False)
ax2.spines["top"].set_visible(False)
ax2.spines["bottom"].set_visible(False)
ax1.set_title(TYPE, fontsize=20)
plt.show()
fig.savefig(TYPE, bbox_inches='tight', dpi=600)
elif self.TYPE == "line":
def line(self, dt, date, carrier, value, value2, TYPE):
dataset = pd.read_csv(dt)
dataset['date'] = pd.to_datetime(dataset[date])
dataset['yq'] = pd.PeriodIndex(dataset['date'], freq='Q')
dataset = dataset.groupby([group, 'yq'])[value, value2].sum().reset_index()
dataset['Arate'] = dataset[value2] / dataset[value]
dataset.yq = dataset.yq.astype(str)
fig, ax1 = plt.subplots(figsize=(12,7))
sns.lineplot(x='yq', y='Arate', data=dataset, hue=group, ax=ax1, linewidth=5)
ax1.set_xticklabels(dataset['yq'], rotation=45, fontsize = 15)
ax1.set_xlabel("")
ax1.set_ylabel("")
ax1.set_ylim((min(dataset['Arate']) - 0.05, max(dataset['Arate']) + 0.05))
ax1.set_yticklabels(['{:.1f}%'.format(a*100) for a in ax1.get_yticks()], fontsize = 18, weight = 'heavy')
ax1.legend(bbox_to_anchor=(0., 1.02, 1., .102), loc=2, borderaxespad=0., ncol = 6)
ax1.yaxis.grid(True)
ax1.spines["right"].set_visible(False)
ax1.spines["left"].set_visible(False)
ax1.spines["top"].set_visible(False)
ax1.spines["bottom"].set_visible(False)
ax1.set_title(TYPE, fontsize = 20)
plt.show()
fig.savefig(TYPE, bbox_inches='tight', dpi=600)
elif self.TYPE == "bar":
def Bar(self, dt, date, group, value3, value4, value5, value6, TYPE):
dataset = pd.read_csv(dt, sep = '|')
dataset['date'] = pd.to_datetime(dataset[date])
dataset['yq'] = pd.PeriodIndex(dataset['date'], freq='Q')
dataset = dataset.groupby([group, 'yq'])[value3, value4, value5, value6].sum().reset_index()
dataset = dataset.groupby([group]).tail(4)
dataset.yq = dataset.yq.astype(str)
dataset = pd.melt(dataset, id_vars = [group, 'yq'], value_vars = [value3, value4, value5, value6])
dataset = dataset.groupby(['variable', group]).value.sum().reset_index()
dataset['L4Qtr'] = dataset.value / dataset.groupby([group]).value.transform('sum')
fig, ax1 = plt.subplots(figsize=(12,7))
sns.barplot(x='variable', y='L4Qtr', data=dataset, hue=group, ax=ax1)
ax1.set_xticklabels(ax1.get_xticklabels(), fontsize=17.5, weight = 'heavy')
ax1.set_xlabel("", fontsize=15)
ax1.set_ylabel("")
ax1.yaxis.set_ticks(np.arange(0, max(dataset['L4Qtr']) + 0.1, 0.05), False)
ax1.set_yticklabels(['{:.1f}%'.format(a*100) for a in ax1.get_yticks()], fontsize = 18, weight = 'heavy')
ax1.legend(bbox_to_anchor=(0., 1.02, 1., .102), loc=2, borderaxespad=0., ncol = 6)
for groups in ax1.containers:
for bar in groups:
ax1.text(
bar.get_xy()[0] + bar.get_width()/2,
bar.get_height() + 0.005,
'{:.1f}%'.format(round(100*bar.get_height(),2)),
color=bar.get_facecolor(),
horizontalalignment='center',
fontsize = 16, weight = 'heavy'
)
ax1.spines["right"].set_visible(False)
ax1.spines["left"].set_visible(False)
ax1.spines["top"].set_visible(False)
ax1.spines["bottom"].set_visible(False)
ax1.set_title(TYPE, fontsize=20)
plt.show()
fig.savefig(TYPE, bbox_inches='tight', dpi=600)
第三,我希望其他人可以简单地使用此模块,如下所示:
import sys
sys.path.append(r'\\users\desktop\module')
from AP import AP as ap
最后,当有人分配TYPE
,它将自动打印并保存它。
# This will plot combo chart
ap(r'\\users\desktop\dataset.csv', date = 'DATEVALUE', group = 'GRPS', value = 'total', TYPE = 'combo')
以上是理想的想法。 我不需要在其中传递value2 ~ value6
,因为combo
不使用它们。
当我想要bar
:
# This will plot bar chart
ap(r'\\users\desktop\dataset.csv', date = 'DATEVALUE', group = 'GRPS', value3 = 'col1', value4 = 'col2', value5 = 'col3', value6 = 'col4', TYPE = 'combo')
由于发生错误,我的代码不正确。 似乎我需要在其中传递所有参数。
但是,即使我在其中传递了所有参数。 没有错误,但没有输出。
有什么建议吗?
您能解释一下,为什么不只为类型创建子类吗? 那不是更直接吗?
1.)一种方法是使子类对用户可见,如果您不喜欢,
2.)您可以只创建一种接口类(例如,AP,该类隐藏在幕后使用的类,例如,在设置类型后立即实例化)。
3.)您可以一开始就可以工作,但是我想您必须使这些方法对用户可见,因为我想您实现该方法的方式是,这些函数仅在init方法中可见(也许您的缩进不可见)非常正确)。 例如,如果您的if语句由init方法执行,则可以将这些方法分配给实例变量,例如self.ComboChart = ComboChart,以便能够从外部调用该方法。 但是,恕我直言,这不是非常pythonic,而是更hacky /更少面向对象。
因此,我建议1.),如果由于某种原因无法实现,那么我将寻求解决方案2。这两种解决方案还允许您形成一个干净的类结构并以这种方式重用代码,同时您仍然可以如果愿意,可以构建简化的接口类。
方法1的示例(伪代码)如下所示。 请注意,我尚未对其进行测试,它仅是为了向您提供有关以面向对象的方式拆分逻辑的想法。 我没有检查您的整个解决方案,因此例如,您是否始终以相同的方式对数据进行分组,就不知道了。 我可能还会将表示逻辑与数据逻辑分开。 如果您打算以更多方式显示相同的数据,那将是一个特别好的主意,因为使用当前的逻辑,您每次需要进行另一次重新呈现时,都将重新读取csv文件并重新处理数据。 因此,在我只想解释基本原理时,不要使其变得更加复杂,而忽略了这一点,并给出了基类“ Chart”和子类“ ComboChart”的示例。 “ ComboChart”类知道如何读取/分组数据,因为它继承了“ Chart”的方法,因此您只需实施一次即可,因此,如果您发现错误或以后想对其进行增强,则只需要在一个地方做。 然后,draw_chart方法仅需要根据所选择的表示做不同的事情。 用户必须根据要显示的图表类型创建子类的实例,然后调用display_chart()。
import pandas as pd
import numpy as np
import seaborn as sns
import matplotlib.pyplot as plt
class Chart(object):
def __init__(self, dt, date, group, value, value2, value3, value4, value5, value6):
self.dt = dt
self.date = date
self.group= carrier
self.value = value
self.col1 = col1
self.col2 = col2
self.col3 = col3
self.col4 = col4
self.TYPE = TYPE
self.dataset= None
def _read_data_(self)
dataset = pd.read_csv(dt)
dataset['date'] = pd.to_datetime(dataset[self.date])
dataset['yq'] = pd.PeriodIndex(dataset['date'], freq='Q')
dataset['qtr'] = dataset['date'].dt.quarter
dataset = dataset.groupby([carrier, 'yq', 'qtr'])[value].sum().reset_index()
dataset['total.YQGR'] = dataset[value] / dataset.groupby(['qtr', carrier])[value].transform('shift') - 1
dataset = dataset[np.isfinite(dataset['total.YQGR'])]
dataset['total.R'] = dataset[value] / dataset.groupby(group)[value].transform('first')
dataset.yq = dataset.yq.astype(str)
self.dataset= dataset
return dataset
def get_data(self):
if self.dataset is None:
self._read_data_()
return self.dataset
def group_data(self):
dataset= self.get_data()
dataset = dataset.groupby([carrier, 'yq', 'qtr'])[value].sum().reset_index()
dataset['total.YQGR'] = dataset[value] / dataset.groupby(['qtr', carrier])[value].transform('shift') - 1
dataset = dataset[np.isfinite(dataset['total.YQGR'])]
dataset['total.R'] = dataset[value] / dataset.groupby(group)[value].transform('first')
dataset.yq = dataset.yq.astype(str)
return dataset
def draw_chart(self):
pass
class ComboChart(Chart):
def draw_chart(self):
dataset = self.group_data()
fig, ax1 = plt.subplots(figsize=(12,7))
ax2=ax1.twinx()
sns.lineplot(x='yq',y='total.R', data=dataset, hue=group, ax=ax1, legend = None, palette = ('navy', 'r'), linewidth=5)
ax1.set_xticklabels(ax1.get_xticks(), rotation=45, fontsize=15, weight = 'heavy')
ax1.set_xlabel("", fontsize=15)
ax1.set_ylabel("")
ax1.set_ylim((0, max(dataset['total.R']) + 0.05))
sns.barplot(x='yq', y='total.YQGR', data=dataset, hue=group, ax=ax2, palette = ('navy', 'r'))
ax2.set_yticklabels(['{:.1f}%'.format(a*100) for a in ax2.get_yticks()])
ax2.set_ylabel("")
ax2.set_ylim((min(dataset['total.YQGR']) - 0.01, max(dataset['total.YQGR']) + 0.2))
ax2.get_legend().remove()
ax2.legend(bbox_to_anchor=(-0.35, 0.5), loc=2, borderaxespad=0., fontsize = 'xx-large')
for groups in ax2.containers:
for bar in groups:
if bar.get_height() >= 0:
ax2.text(
bar.get_xy()[0] + bar.get_width()/1.5,
bar.get_height() + 0.003,
'{:.1f}%'.format(round(100*bar.get_height(),2)),
color='black',
horizontalalignment='center',
fontsize = 12, weight = 'heavy'
)
else:
ax2.text(
bar.get_xy()[0] + bar.get_width()/1.5,
bar.get_height() - 0.008,
'{:.1f}%'.format(round(100*bar.get_height(),2)),
color='black',
horizontalalignment='center',
fontsize = 12, weight = 'heavy'
)
ax1.yaxis.set_visible(False)
ax2.yaxis.set_visible(False)
ax2.xaxis.set_visible(False)
ax1.spines["right"].set_visible(False)
ax1.spines["left"].set_visible(False)
ax1.spines["top"].set_visible(False)
ax1.spines["bottom"].set_visible(False)
ax2.spines["right"].set_visible(False)
ax2.spines["left"].set_visible(False)
ax2.spines["top"].set_visible(False)
ax2.spines["bottom"].set_visible(False)
ax1.set_title(TYPE, fontsize=20)
plt.show()
fig.savefig(TYPE, bbox_inches='tight', dpi=600)
第二种方法(带有接口类)看起来是一样的,只是您拥有用户已知的第四类,并且知道如何调用真正的实现。 像这样:
class YourInterface:
def __init__(self, your_arguments, TYPE):
if TYPE == __ 'ComboChart':
self.client= ComboChart(your_arguments)
elif TYPE == ....
def display_chart(self):
self.client.display_chart()
但这是一个很无聊的课,不是吗? 如果您的类层次结构非常技术性,并且如果您想避免库的用户建立对真实类层次结构的依赖关系,而这种依赖关系可能会在您更改层次结构后立即破坏,那么我只会这样做。 我猜在大多数情况下,类层次结构保持相对稳定,因此您不需要接口类创建的额外抽象级别。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.